Skip to content
Permalink
Browse files
8242643: Shenandoah: split concurrent weak and strong root processing
Reviewed-by: shade
  • Loading branch information
zhengyu123 committed Apr 15, 2020
1 parent 346d09e commit 23709c830e2ea206a575662407535508219a0ca8
Showing 9 changed files with 80 additions and 55 deletions.
@@ -88,7 +88,9 @@ ShenandoahEvacuateUpdateRootsClosure<MO>::ShenandoahEvacuateUpdateRootsClosure()
template <DecoratorSet MO>
template <class T>
void ShenandoahEvacuateUpdateRootsClosure<MO>::do_oop_work(T* p) {
assert(_heap->is_concurrent_root_in_progress(), "Only do this when evacuation is in progress");
assert(_heap->is_concurrent_weak_root_in_progress() ||
_heap->is_concurrent_strong_root_in_progress(),
"Only do this in root processing phase");

T o = RawAccess<>::oop_load(p);
if (! CompressedOops::is_null(o)) {
@@ -119,7 +121,9 @@ ShenandoahEvacUpdateOopStorageRootsClosure::ShenandoahEvacUpdateOopStorageRootsC
}

void ShenandoahEvacUpdateOopStorageRootsClosure::do_oop(oop* p) {
assert(_heap->is_concurrent_root_in_progress(), "Only do this when evacuation is in progress");
assert(_heap->is_concurrent_weak_root_in_progress() ||
_heap->is_concurrent_strong_root_in_progress(),
"Only do this in root processing phase");

oop obj = RawAccess<>::oop_load(p);
if (! CompressedOops::is_null(obj)) {
@@ -248,7 +248,7 @@ class ShenandoahNMethodUnlinkClosure : public NMethodClosure {
_bs(ShenandoahBarrierSet::barrier_set()->barrier_set_nmethod()) {}

virtual void do_nmethod(nmethod* nm) {
assert(_heap->is_concurrent_root_in_progress(), "Only this phase");
assert(_heap->is_concurrent_weak_root_in_progress(), "Only this phase");
if (failed()) {
return;
}
@@ -342,8 +342,8 @@ void ShenandoahControlThread::service_concurrent_normal_cycle(GCCause::Cause cau
// Complete marking under STW, and start evacuation
heap->vmop_entry_final_mark();

// Evacuate concurrent roots
heap->entry_roots();
// Process weak roots that might still point to regions that would be broken by cleanup
heap->entry_weak_roots();

// Final mark might have reclaimed some immediate garbage, kick cleanup to reclaim
// the space. This would be the last action if there is nothing to evacuate.
@@ -354,6 +354,13 @@ void ShenandoahControlThread::service_concurrent_normal_cycle(GCCause::Cause cau
heap->free_set()->log_status();
}

// Processing strong roots
// This may be skipped if there is nothing to update/evacuate.
// If so, strong_root_in_progress would be unset.
if (heap->is_concurrent_strong_root_in_progress()) {
heap->entry_strong_roots();
}

// Continue the cycle with evacuation and optional update-refs.
// This may be skipped if there is nothing to evacuate.
// If so, evac_in_progress would be unset by collection set preparation code.
@@ -554,14 +554,16 @@ void ShenandoahHeap::print_on(outputStream* st) const {
proper_unit_for_byte_size(ShenandoahHeapRegion::region_size_bytes()));

st->print("Status: ");
if (has_forwarded_objects()) st->print("has forwarded objects, ");
if (is_concurrent_mark_in_progress()) st->print("marking, ");
if (is_evacuation_in_progress()) st->print("evacuating, ");
if (is_update_refs_in_progress()) st->print("updating refs, ");
if (is_degenerated_gc_in_progress()) st->print("degenerated gc, ");
if (is_full_gc_in_progress()) st->print("full gc, ");
if (is_full_gc_move_in_progress()) st->print("full gc move, ");
if (is_concurrent_root_in_progress()) st->print("concurrent roots, ");
if (has_forwarded_objects()) st->print("has forwarded objects, ");
if (is_concurrent_mark_in_progress()) st->print("marking, ");
if (is_evacuation_in_progress()) st->print("evacuating, ");
if (is_update_refs_in_progress()) st->print("updating refs, ");
if (is_degenerated_gc_in_progress()) st->print("degenerated gc, ");
if (is_full_gc_in_progress()) st->print("full gc, ");
if (is_full_gc_move_in_progress()) st->print("full gc move, ");
if (is_concurrent_weak_root_in_progress()) st->print("concurrent weak roots, ");
if (is_concurrent_strong_root_in_progress() &&
!is_concurrent_weak_root_in_progress()) st->print("concurrent strong roots, ");

if (cancelled_gc()) {
st->print("cancelled");
@@ -1631,15 +1633,12 @@ void ShenandoahHeap::op_cleanup() {
class ShenandoahConcurrentRootsEvacUpdateTask : public AbstractGangTask {
private:
ShenandoahVMRoots<true /*concurrent*/> _vm_roots;
ShenandoahWeakRoots<true /*concurrent*/> _weak_roots;
ShenandoahClassLoaderDataRoots<true /*concurrent*/, false /*single threaded*/> _cld_roots;
ShenandoahConcurrentStringDedupRoots _dedup_roots;
bool _include_weak_roots;

public:
ShenandoahConcurrentRootsEvacUpdateTask(bool include_weak_roots) :
AbstractGangTask("Shenandoah Evacuate/Update Concurrent Roots Task"),
_include_weak_roots(include_weak_roots) {
ShenandoahConcurrentRootsEvacUpdateTask() :
AbstractGangTask("Shenandoah Evacuate/Update Concurrent Strong Roots Task") {
}

void work(uint worker_id) {
@@ -1649,10 +1648,6 @@ class ShenandoahConcurrentRootsEvacUpdateTask : public AbstractGangTask {
// may race against OopStorage::release() calls.
ShenandoahEvacUpdateOopStorageRootsClosure cl;
_vm_roots.oops_do<ShenandoahEvacUpdateOopStorageRootsClosure>(&cl);

if (_include_weak_roots) {
_weak_roots.oops_do<ShenandoahEvacUpdateOopStorageRootsClosure>(&cl);
}
}

{
@@ -1771,26 +1766,26 @@ class ShenandoahConcurrentWeakRootsEvacUpdateTask : public AbstractGangTask {
}
};

void ShenandoahHeap::op_roots() {
if (is_concurrent_root_in_progress()) {
if (ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) {
// Concurrent weak root processing
ShenandoahConcurrentWeakRootsEvacUpdateTask task;
workers()->run_task(&task);
void ShenandoahHeap::op_weak_roots() {
if (is_concurrent_weak_root_in_progress()) {
// Concurrent weak root processing
ShenandoahConcurrentWeakRootsEvacUpdateTask task;
workers()->run_task(&task);

if (ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) {
_unloader.unload();
set_concurrent_weak_root_in_progress(false);
}

if (ShenandoahConcurrentRoots::should_do_concurrent_roots()) {
ShenandoahConcurrentRootsEvacUpdateTask task(!ShenandoahConcurrentRoots::should_do_concurrent_class_unloading());
workers()->run_task(&task);
}
set_concurrent_weak_root_in_progress(false);
set_concurrent_root_in_progress(false);
}
}

void ShenandoahHeap::op_strong_roots() {
assert(is_concurrent_strong_root_in_progress(), "Checked by caller");
ShenandoahConcurrentRootsEvacUpdateTask task;
workers()->run_task(&task);
set_concurrent_strong_root_in_progress(false);
}

class ShenandoahResetUpdateRegionStateClosure : public ShenandoahHeapRegionClosure {
private:
ShenandoahMarkingContext* const _ctx;
@@ -2038,12 +2033,12 @@ void ShenandoahHeap::set_evacuation_in_progress(bool in_progress) {
set_gc_state_mask(EVACUATION, in_progress);
}

void ShenandoahHeap::set_concurrent_root_in_progress(bool in_progress) {
void ShenandoahHeap::set_concurrent_strong_root_in_progress(bool in_progress) {
assert(ShenandoahConcurrentRoots::can_do_concurrent_roots(), "Why set the flag?");
if (in_progress) {
_concurrent_root_in_progress.set();
_concurrent_strong_root_in_progress.set();
} else {
_concurrent_root_in_progress.unset();
_concurrent_strong_root_in_progress.unset();
}
}

@@ -2333,7 +2328,7 @@ ConcurrentGCTimer* ShenandoahHeap::gc_timer() const {
void ShenandoahHeap::prepare_concurrent_roots() {
assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
if (ShenandoahConcurrentRoots::should_do_concurrent_roots()) {
set_concurrent_root_in_progress(true);
set_concurrent_strong_root_in_progress(!collection_set()->is_empty());
set_concurrent_weak_root_in_progress(true);
}
}
@@ -2841,19 +2836,34 @@ void ShenandoahHeap::entry_updaterefs() {
op_updaterefs();
}

void ShenandoahHeap::entry_roots() {
static const char* msg = "Concurrent roots processing";
void ShenandoahHeap::entry_weak_roots() {
static const char* msg = "Concurrent weak roots";
ShenandoahConcurrentPhase gc_phase(msg);
EventMark em("%s", msg);

ShenandoahGCPhase phase(ShenandoahPhaseTimings::conc_weak_roots);

ShenandoahWorkerScope scope(workers(),
ShenandoahWorkerPolicy::calc_workers_for_conc_root_processing(),
"concurrent weak root");

try_inject_alloc_failure();
op_weak_roots();
}

void ShenandoahHeap::entry_strong_roots() {
static const char* msg = "Concurrent strong roots";
ShenandoahConcurrentPhase gc_phase(msg);
EventMark em("%s", msg);

ShenandoahGCPhase phase(ShenandoahPhaseTimings::conc_roots);
ShenandoahGCPhase phase(ShenandoahPhaseTimings::conc_strong_roots);

ShenandoahWorkerScope scope(workers(),
ShenandoahWorkerPolicy::calc_workers_for_conc_root_processing(),
"concurrent root processing");
"concurrent strong root");

try_inject_alloc_failure();
op_roots();
op_strong_roots();
}

void ShenandoahHeap::entry_cleanup() {
@@ -276,7 +276,7 @@ class ShenandoahHeap : public CollectedHeap {
ShenandoahSharedFlag _full_gc_in_progress;
ShenandoahSharedFlag _full_gc_move_in_progress;
ShenandoahSharedFlag _progress_last_gc;
ShenandoahSharedFlag _concurrent_root_in_progress;
ShenandoahSharedFlag _concurrent_strong_root_in_progress;
ShenandoahSharedFlag _concurrent_weak_root_in_progress;

void set_gc_state_all_threads(char state);
@@ -293,7 +293,7 @@ class ShenandoahHeap : public CollectedHeap {
void set_full_gc_in_progress(bool in_progress);
void set_full_gc_move_in_progress(bool in_progress);
void set_has_forwarded_objects(bool cond);
void set_concurrent_root_in_progress(bool cond);
void set_concurrent_strong_root_in_progress(bool cond);
void set_concurrent_weak_root_in_progress(bool cond);

inline bool is_stable() const;
@@ -307,7 +307,7 @@ class ShenandoahHeap : public CollectedHeap {
inline bool has_forwarded_objects() const;
inline bool is_gc_in_progress_mask(uint mask) const;
inline bool is_stw_gc_in_progress() const;
inline bool is_concurrent_root_in_progress() const;
inline bool is_concurrent_strong_root_in_progress() const;
inline bool is_concurrent_weak_root_in_progress() const;

// ---------- GC cancellation and degeneration machinery
@@ -397,7 +397,8 @@ class ShenandoahHeap : public CollectedHeap {
void entry_reset();
void entry_mark();
void entry_preclean();
void entry_roots();
void entry_weak_roots();
void entry_strong_roots();
void entry_cleanup();
void entry_evac();
void entry_updaterefs();
@@ -417,7 +418,8 @@ class ShenandoahHeap : public CollectedHeap {
void op_reset();
void op_mark();
void op_preclean();
void op_roots();
void op_weak_roots();
void op_strong_roots();
void op_cleanup();
void op_conc_evac();
void op_stw_evac();
@@ -378,8 +378,8 @@ inline bool ShenandoahHeap::is_stw_gc_in_progress() const {
return is_full_gc_in_progress() || is_degenerated_gc_in_progress();
}

inline bool ShenandoahHeap::is_concurrent_root_in_progress() const {
return _concurrent_root_in_progress.is_set();
inline bool ShenandoahHeap::is_concurrent_strong_root_in_progress() const {
return _concurrent_strong_root_in_progress.is_set();
}

inline bool ShenandoahHeap::is_concurrent_weak_root_in_progress() const {
@@ -75,10 +75,11 @@ void ShenandoahMarkCompact::do_it(GCCause::Cause gc_cause) {
Universe::verify();
}

// Degenerated GC may carry concurrent_root_in_progress flag when upgrading to
// Degenerated GC may carry concurrent root flags when upgrading to
// full GC. We need to reset it before mutators resume.
if (ShenandoahConcurrentRoots::can_do_concurrent_class_unloading()) {
heap->set_concurrent_root_in_progress(false);
heap->set_concurrent_strong_root_in_progress(false);
heap->set_concurrent_weak_root_in_progress(false);
}

heap->set_full_gc_in_progress(true);
@@ -136,7 +136,8 @@ class outputStream;
f(conc_reset, "Concurrent Reset") \
f(conc_mark, "Concurrent Marking") \
f(conc_preclean, "Concurrent Precleaning") \
f(conc_roots, "Concurrent Roots") \
f(conc_weak_roots, "Concurrent Weak Roots") \
f(conc_strong_roots, "Concurrent Strong Roots") \
f(conc_evac, "Concurrent Evacuation") \
f(conc_update_refs, "Concurrent Update Refs") \
f(conc_cleanup, "Concurrent Cleanup") \
@@ -79,7 +79,7 @@ class ShenandoahIsUnloadingBehaviour : public IsUnloadingBehaviour {
public:
virtual bool is_unloading(CompiledMethod* method) const {
nmethod* const nm = method->as_nmethod();
assert(ShenandoahHeap::heap()->is_concurrent_root_in_progress(), "Only for this phase");
assert(ShenandoahHeap::heap()->is_concurrent_weak_root_in_progress(), "Only for this phase");
ShenandoahNMethod* data = ShenandoahNMethod::gc_data(nm);
ShenandoahReentrantLocker locker(data->lock());
ShenandoahIsUnloadingOopClosure cl;

0 comments on commit 23709c8

Please sign in to comment.