8217858: ZGC: Clean up ZDriver

Reviewed-by: stefank, eosterlund
This commit is contained in:
Per Lidén 2019-01-29 10:23:38 +01:00
parent 62e8d6f43b
commit 9f3059e20c
3 changed files with 168 additions and 158 deletions

View file

@ -44,7 +44,6 @@ static const ZStatPhasePause ZPhasePauseMarkEnd("Pause Mark End");
static const ZStatPhaseConcurrent ZPhaseConcurrentProcessNonStrongReferences("Concurrent Process Non-Strong References"); static const ZStatPhaseConcurrent ZPhaseConcurrentProcessNonStrongReferences("Concurrent Process Non-Strong References");
static const ZStatPhaseConcurrent ZPhaseConcurrentResetRelocationSet("Concurrent Reset Relocation Set"); static const ZStatPhaseConcurrent ZPhaseConcurrentResetRelocationSet("Concurrent Reset Relocation Set");
static const ZStatPhaseConcurrent ZPhaseConcurrentDestroyDetachedPages("Concurrent Destroy Detached Pages"); static const ZStatPhaseConcurrent ZPhaseConcurrentDestroyDetachedPages("Concurrent Destroy Detached Pages");
static const ZStatPhasePause ZPhasePauseVerify("Pause Verify");
static const ZStatPhaseConcurrent ZPhaseConcurrentSelectRelocationSet("Concurrent Select Relocation Set"); static const ZStatPhaseConcurrent ZPhaseConcurrentSelectRelocationSet("Concurrent Select Relocation Set");
static const ZStatPhaseConcurrent ZPhaseConcurrentPrepareRelocationSet("Concurrent Prepare Relocation Set"); static const ZStatPhaseConcurrent ZPhaseConcurrentPrepareRelocationSet("Concurrent Prepare Relocation Set");
static const ZStatPhasePause ZPhasePauseRelocateStart("Pause Relocate Start"); static const ZStatPhasePause ZPhasePauseRelocateStart("Pause Relocate Start");
@ -52,41 +51,26 @@ static const ZStatPhaseConcurrent ZPhaseConcurrentRelocated("Concurrent Relocate
static const ZStatCriticalPhase ZCriticalPhaseGCLockerStall("GC Locker Stall", false /* verbose */); static const ZStatCriticalPhase ZCriticalPhaseGCLockerStall("GC Locker Stall", false /* verbose */);
static const ZStatSampler ZSamplerJavaThreads("System", "Java Threads", ZStatUnitThreads); static const ZStatSampler ZSamplerJavaThreads("System", "Java Threads", ZStatUnitThreads);
class ZOperationClosure : public StackObj { class VM_ZOperation : public VM_Operation {
private:
const uint _gc_id;
bool _gc_locked;
bool _success;
public: public:
virtual const char* name() const = 0; VM_ZOperation() :
_gc_id(GCId::current()),
_gc_locked(false),
_success(false) {}
virtual bool needs_inactive_gc_locker() const { virtual bool needs_inactive_gc_locker() const {
// An inactive GC locker is needed in operations where we change the good // An inactive GC locker is needed in operations where we change the bad
// mask or move objects. Changing the good mask will invalidate all oops, // mask or move objects. Changing the bad mask will invalidate all oops,
// which makes it conceptually the same thing as moving all objects. // which makes it conceptually the same thing as moving all objects.
return false; return false;
} }
virtual bool do_operation() = 0; virtual bool do_operation() = 0;
};
class VM_ZOperation : public VM_Operation {
private:
ZOperationClosure* _cl;
uint _gc_id;
bool _gc_locked;
bool _success;
public:
VM_ZOperation(ZOperationClosure* cl) :
_cl(cl),
_gc_id(GCId::current()),
_gc_locked(false),
_success(false) {}
virtual VMOp_Type type() const {
return VMOp_ZOperation;
}
virtual const char* name() const {
return _cl->name();
}
virtual bool doit_prologue() { virtual bool doit_prologue() {
Heap_lock->lock(); Heap_lock->lock();
@ -94,28 +78,28 @@ public:
} }
virtual void doit() { virtual void doit() {
assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); // Abort if GC locker state is incompatible
if (needs_inactive_gc_locker() && GCLocker::check_active_before_gc()) {
ZStatSample(ZSamplerJavaThreads, Threads::number_of_threads());
// Setup GC id
GCIdMark gcid(_gc_id);
if (_cl->needs_inactive_gc_locker() && GCLocker::check_active_before_gc()) {
// GC locker is active, bail out
_gc_locked = true; _gc_locked = true;
} else { return;
// Execute operation
IsGCActiveMark mark;
_success = _cl->do_operation();
} }
// Setup GC id and active marker
GCIdMark gc_id_mark(_gc_id);
IsGCActiveMark gc_active_mark;
// Execute operation
_success = do_operation();
// Update statistics
ZStatSample(ZSamplerJavaThreads, Threads::number_of_threads());
} }
virtual void doit_epilogue() { virtual void doit_epilogue() {
Heap_lock->unlock(); Heap_lock->unlock();
} }
bool gc_locked() { bool gc_locked() const {
return _gc_locked; return _gc_locked;
} }
@ -165,10 +149,10 @@ static bool should_boost_worker_threads() {
return false; return false;
} }
class ZMarkStartClosure : public ZOperationClosure { class VM_ZMarkStart : public VM_ZOperation {
public: public:
virtual const char* name() const { virtual VMOp_Type type() const {
return "ZMarkStart"; return VMOp_ZMarkStart;
} }
virtual bool needs_inactive_gc_locker() const { virtual bool needs_inactive_gc_locker() const {
@ -194,37 +178,23 @@ public:
} }
}; };
class ZMarkEndClosure : public ZOperationClosure { class VM_ZMarkEnd : public VM_ZOperation {
public: public:
virtual const char* name() const { virtual VMOp_Type type() const {
return "ZMarkEnd"; return VMOp_ZMarkEnd;
} }
virtual bool do_operation() { virtual bool do_operation() {
ZStatTimer timer(ZPhasePauseMarkEnd); ZStatTimer timer(ZPhasePauseMarkEnd);
ZServiceabilityMarkEndTracer tracer; ZServiceabilityMarkEndTracer tracer;
return ZHeap::heap()->mark_end(); return ZHeap::heap()->mark_end();
} }
}; };
class ZVerifyClosure : public ZOperationClosure { class VM_ZRelocateStart : public VM_ZOperation {
public: public:
virtual const char* name() const { virtual VMOp_Type type() const {
return "ZVerify"; return VMOp_ZRelocateStart;
}
virtual bool do_operation() {
ZStatTimer timer(ZPhasePauseVerify);
Universe::verify();
return true;
}
};
class ZRelocateStartClosure : public ZOperationClosure {
public:
virtual const char* name() const {
return "ZRelocateStart";
} }
virtual bool needs_inactive_gc_locker() const { virtual bool needs_inactive_gc_locker() const {
@ -234,7 +204,6 @@ public:
virtual bool do_operation() { virtual bool do_operation() {
ZStatTimer timer(ZPhasePauseRelocateStart); ZStatTimer timer(ZPhasePauseRelocateStart);
ZServiceabilityRelocateStartTracer tracer; ZServiceabilityRelocateStartTracer tracer;
ZHeap::heap()->relocate_start(); ZHeap::heap()->relocate_start();
return true; return true;
} }
@ -247,24 +216,6 @@ ZDriver::ZDriver() :
create_and_start(); create_and_start();
} }
bool ZDriver::vm_operation(ZOperationClosure* cl) {
for (;;) {
VM_ZOperation op(cl);
VMThread::execute(&op);
if (op.gc_locked()) {
// Wait for GC to become unlocked and restart the VM operation
ZStatTimer timer(ZCriticalPhaseGCLockerStall);
_gc_locker_port.wait();
continue;
}
// Notify VM operation completed
_gc_locker_port.ack();
return op.success();
}
}
void ZDriver::collect(GCCause::Cause cause) { void ZDriver::collect(GCCause::Cause cause) {
switch (cause) { switch (cause) {
case GCCause::_wb_young_gc: case GCCause::_wb_young_gc:
@ -302,19 +253,96 @@ void ZDriver::collect(GCCause::Cause cause) {
} }
} }
GCCause::Cause ZDriver::start_gc_cycle() { template <typename T>
// Wait for GC request bool ZDriver::pause() {
return _gc_cycle_port.receive(); for (;;) {
T op;
VMThread::execute(&op);
if (op.gc_locked()) {
// Wait for GC to become unlocked and restart the VM operation
ZStatTimer timer(ZCriticalPhaseGCLockerStall);
_gc_locker_port.wait();
continue;
}
// Notify VM operation completed
_gc_locker_port.ack();
return op.success();
}
} }
class ZDriverCycleScope : public StackObj { void ZDriver::pause_mark_start() {
pause<VM_ZMarkStart>();
}
void ZDriver::concurrent_mark() {
ZStatTimer timer(ZPhaseConcurrentMark);
ZHeap::heap()->mark(true /* initial */);
}
bool ZDriver::pause_mark_end() {
return pause<VM_ZMarkEnd>();
}
void ZDriver::concurrent_mark_continue() {
ZStatTimer timer(ZPhaseConcurrentMarkContinue);
ZHeap::heap()->mark(false /* initial */);
}
void ZDriver::concurrent_process_non_strong_references() {
ZStatTimer timer(ZPhaseConcurrentProcessNonStrongReferences);
ZHeap::heap()->process_non_strong_references();
}
void ZDriver::concurrent_reset_relocation_set() {
ZStatTimer timer(ZPhaseConcurrentResetRelocationSet);
ZHeap::heap()->reset_relocation_set();
}
void ZDriver::concurrent_destroy_detached_pages() {
ZStatTimer timer(ZPhaseConcurrentDestroyDetachedPages);
ZHeap::heap()->destroy_detached_pages();
}
void ZDriver::pause_verify() {
if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) {
VM_Verify op;
VMThread::execute(&op);
}
}
void ZDriver::concurrent_select_relocation_set() {
ZStatTimer timer(ZPhaseConcurrentSelectRelocationSet);
ZHeap::heap()->select_relocation_set();
}
void ZDriver::concurrent_prepare_relocation_set() {
ZStatTimer timer(ZPhaseConcurrentPrepareRelocationSet);
ZHeap::heap()->prepare_relocation_set();
}
void ZDriver::pause_relocate_start() {
pause<VM_ZRelocateStart>();
}
void ZDriver::concurrent_relocate() {
ZStatTimer timer(ZPhaseConcurrentRelocated);
ZHeap::heap()->relocate();
}
void ZDriver::check_out_of_memory() {
ZHeap::heap()->check_out_of_memory();
}
class ZDriverGCScope : public StackObj {
private: private:
GCIdMark _gc_id; GCIdMark _gc_id;
GCCauseSetter _gc_cause_setter; GCCauseSetter _gc_cause_setter;
ZStatTimer _timer; ZStatTimer _timer;
public: public:
ZDriverCycleScope(GCCause::Cause cause) : ZDriverGCScope(GCCause::Cause cause) :
_gc_id(), _gc_id(),
_gc_cause_setter(ZCollectedHeap::heap(), cause), _gc_cause_setter(ZCollectedHeap::heap(), cause),
_timer(ZPhaseCycle) { _timer(ZPhaseCycle) {
@ -322,7 +350,7 @@ public:
ZStatCycle::at_start(); ZStatCycle::at_start();
} }
~ZDriverCycleScope() { ~ZDriverGCScope() {
// Calculate boost factor // Calculate boost factor
const double boost_factor = (double)ZHeap::heap()->nconcurrent_worker_threads() / const double boost_factor = (double)ZHeap::heap()->nconcurrent_worker_threads() /
(double)ZHeap::heap()->nconcurrent_no_boost_worker_threads(); (double)ZHeap::heap()->nconcurrent_no_boost_worker_threads();
@ -335,96 +363,63 @@ public:
} }
}; };
void ZDriver::run_gc_cycle(GCCause::Cause cause) { void ZDriver::gc(GCCause::Cause cause) {
ZDriverCycleScope scope(cause); ZDriverGCScope scope(cause);
// Phase 1: Pause Mark Start // Phase 1: Pause Mark Start
{ pause_mark_start();
ZMarkStartClosure cl;
vm_operation(&cl);
}
// Phase 2: Concurrent Mark // Phase 2: Concurrent Mark
{ concurrent_mark();
ZStatTimer timer(ZPhaseConcurrentMark);
ZHeap::heap()->mark(true /* initial */);
}
// Phase 3: Pause Mark End // Phase 3: Pause Mark End
{ while (!pause_mark_end()) {
ZMarkEndClosure cl; // Phase 3.5: Concurrent Mark Continue
while (!vm_operation(&cl)) { concurrent_mark_continue();
// Phase 3.5: Concurrent Mark Continue
ZStatTimer timer(ZPhaseConcurrentMarkContinue);
ZHeap::heap()->mark(false /* initial */);
}
} }
// Phase 4: Concurrent Process Non-Strong References // Phase 4: Concurrent Process Non-Strong References
{ concurrent_process_non_strong_references();
ZStatTimer timer(ZPhaseConcurrentProcessNonStrongReferences);
ZHeap::heap()->process_non_strong_references();
}
// Phase 5: Concurrent Reset Relocation Set // Phase 5: Concurrent Reset Relocation Set
{ concurrent_reset_relocation_set();
ZStatTimer timer(ZPhaseConcurrentResetRelocationSet);
ZHeap::heap()->reset_relocation_set();
}
// Phase 6: Concurrent Destroy Detached Pages // Phase 6: Concurrent Destroy Detached Pages
{ concurrent_destroy_detached_pages();
ZStatTimer timer(ZPhaseConcurrentDestroyDetachedPages);
ZHeap::heap()->destroy_detached_pages();
}
// Phase 7: Pause Verify // Phase 7: Pause Verify
if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) { pause_verify();
ZVerifyClosure cl;
vm_operation(&cl);
}
// Phase 8: Concurrent Select Relocation Set // Phase 8: Concurrent Select Relocation Set
{ concurrent_select_relocation_set();
ZStatTimer timer(ZPhaseConcurrentSelectRelocationSet);
ZHeap::heap()->select_relocation_set();
}
// Phase 9: Concurrent Prepare Relocation Set // Phase 9: Concurrent Prepare Relocation Set
{ concurrent_prepare_relocation_set();
ZStatTimer timer(ZPhaseConcurrentPrepareRelocationSet);
ZHeap::heap()->prepare_relocation_set();
}
// Phase 10: Pause Relocate Start // Phase 10: Pause Relocate Start
{ pause_relocate_start();
ZRelocateStartClosure cl;
vm_operation(&cl);
}
// Phase 11: Concurrent Relocate // Phase 11: Concurrent Relocate
{ concurrent_relocate();
ZStatTimer timer(ZPhaseConcurrentRelocated);
ZHeap::heap()->relocate();
}
}
void ZDriver::end_gc_cycle() {
// Notify GC cycle completed
_gc_cycle_port.ack();
// Check for out of memory condition
ZHeap::heap()->check_out_of_memory();
} }
void ZDriver::run_service() { void ZDriver::run_service() {
// Main loop // Main loop
while (!should_terminate()) { while (!should_terminate()) {
const GCCause::Cause cause = start_gc_cycle(); // Wait for GC request
if (cause != GCCause::_no_gc) { const GCCause::Cause cause = _gc_cycle_port.receive();
run_gc_cycle(cause); if (cause == GCCause::_no_gc) {
end_gc_cycle(); continue;
} }
// Run GC
gc(cause);
// Notify GC completed
_gc_cycle_port.ack();
// Check for out of memory condition
check_out_of_memory();
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -28,18 +28,31 @@
#include "gc/shared/gcCause.hpp" #include "gc/shared/gcCause.hpp"
#include "gc/z/zMessagePort.hpp" #include "gc/z/zMessagePort.hpp"
class ZOperationClosure; class VM_ZOperation;
class ZDriver : public ConcurrentGCThread { class ZDriver : public ConcurrentGCThread {
private: private:
ZMessagePort<GCCause::Cause> _gc_cycle_port; ZMessagePort<GCCause::Cause> _gc_cycle_port;
ZRendezvousPort _gc_locker_port; ZRendezvousPort _gc_locker_port;
bool vm_operation(ZOperationClosure* cl); template <typename T> bool pause();
GCCause::Cause start_gc_cycle(); void pause_mark_start();
void run_gc_cycle(GCCause::Cause cause); void concurrent_mark();
void end_gc_cycle(); bool pause_mark_end();
void concurrent_mark_continue();
void concurrent_process_non_strong_references();
void concurrent_reset_relocation_set();
void concurrent_destroy_detached_pages();
void pause_verify();
void concurrent_select_relocation_set();
void concurrent_prepare_relocation_set();
void pause_relocate_start();
void concurrent_relocate();
void check_out_of_memory();
void gc(GCCause::Cause cause);
protected: protected:
virtual void run_service(); virtual void run_service();

View file

@ -68,7 +68,9 @@
template(G1CollectForAllocation) \ template(G1CollectForAllocation) \
template(G1CollectFull) \ template(G1CollectFull) \
template(G1Concurrent) \ template(G1Concurrent) \
template(ZOperation) \ template(ZMarkStart) \
template(ZMarkEnd) \
template(ZRelocateStart) \
template(HandshakeOneThread) \ template(HandshakeOneThread) \
template(HandshakeAllThreads) \ template(HandshakeAllThreads) \
template(HandshakeFallback) \ template(HandshakeFallback) \