--- old/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp 2019-06-11 20:26:15.920683581 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp 2019-06-11 20:26:15.470682781 -0400 @@ -38,6 +38,7 @@ #include "gc/shenandoah/shenandoahCollectionSet.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahConcurrentMark.inline.hpp" +#include "gc/shenandoah/shenandoahConcurrentRoots.hpp" #include "gc/shenandoah/shenandoahControlThread.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" @@ -949,7 +950,7 @@ void work(uint worker_id) { if (_concurrent) { ShenandoahConcurrentWorkerSession worker_session(worker_id); - ShenandoahSuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers); + ShenandoahSuspendibleThreadSetJoiner stsj; ShenandoahEvacOOMScope oom_evac_scope; do_work(); } else { @@ -1071,9 +1072,11 @@ DerivedPointerTable::clear(); #endif assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Only iterate roots while world is stopped"); - { - ShenandoahRootEvacuator rp(workers()->active_workers(), ShenandoahPhaseTimings::init_evac); + // Include concurrent roots if current cycle can not process those roots concurrently + bool include_concurrent_roots = !ShenandoahConcurrentRoots::should_do_concurrent_roots(); + + ShenandoahRootEvacuator rp(workers()->active_workers(), ShenandoahPhaseTimings::init_evac, include_concurrent_roots); ShenandoahEvacuateUpdateRootsTask roots_task(&rp); workers()->run_task(&roots_task); } @@ -1517,7 +1520,12 @@ } if (ShenandoahVerify) { - verifier()->verify_roots_no_forwarded(); + if (ShenandoahConcurrentRoots::should_do_concurrent_roots()) { + ShenandoahRootVerifier::RootTypes types = ShenandoahRootVerifier::combine(ShenandoahRootVerifier::JNIHandleRoots, ShenandoahRootVerifier::CLDGRoots); + verifier()->verify_roots_no_forwarded_except(types); + } else { + verifier()->verify_roots_no_forwarded(); + } verifier()->verify_during_evacuation(); } } else { @@ -1578,6 +1586,34 @@ free_set()->recycle_trash(); } +class ShenandoahConcurrentRootsEvacUpdateTask : public AbstractGangTask { +private: + SuspendibleThreadSetJoiner _sts_joiner; + ShenandoahJNIHandleRoots _jni_roots; + ShenandoahClassLoaderDataRoots _cld_roots; +public: + ShenandoahConcurrentRootsEvacUpdateTask() : + AbstractGangTask("Shenandoah Evacuate/Update Concurrent Roots Task") { + } + + void work(uint worker_id) { + ShenandoahEvacOOMScope oom; + ShenandoahEvacuateUpdateRootsClosure cl; + CLDToOopClosure clds(&cl, ClassLoaderData::_claim_strong); + + _jni_roots.oops_do(&cl); + _cld_roots.cld_do(&clds); + } +}; + +void ShenandoahHeap::op_concurrent_roots() { + if (is_evacuation_in_progress() && + ShenandoahConcurrentRoots::should_do_concurrent_roots()) { + ShenandoahConcurrentRootsEvacUpdateTask task; + workers()->run_task(&task); + } +} + void ShenandoahHeap::op_reset() { reset_mark_bitmap(); } @@ -1851,7 +1887,6 @@ jbyte prev = _cancelled_gc.cmpxchg(CANCELLED, CANCELLABLE); if (prev == CANCELLABLE) return true; else if (prev == CANCELLED) return false; - assert(ShenandoahSuspendibleWorkers, "should not get here when not using suspendible workers"); assert(prev == NOT_CANCELLED, "must be NOT_CANCELLED"); { // We need to provide a safepoint here, otherwise we might @@ -2065,7 +2100,7 @@ void work(uint worker_id) { if (_concurrent) { ShenandoahConcurrentWorkerSession worker_session(worker_id); - ShenandoahSuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers); + ShenandoahSuspendibleThreadSetJoiner stsj; do_work(); } else { ShenandoahParallelWorkerSession worker_session(worker_id); @@ -2265,15 +2300,11 @@ } void ShenandoahHeap::safepoint_synchronize_begin() { - if (ShenandoahSuspendibleWorkers || UseStringDeduplication) { - SuspendibleThreadSet::synchronize(); - } + SuspendibleThreadSet::synchronize(); } void ShenandoahHeap::safepoint_synchronize_end() { - if (ShenandoahSuspendibleWorkers || UseStringDeduplication) { - SuspendibleThreadSet::desynchronize(); - } + SuspendibleThreadSet::desynchronize(); } void ShenandoahHeap::vmop_entry_init_mark() { @@ -2538,6 +2569,22 @@ try_inject_alloc_failure(); op_updaterefs(); } + +void ShenandoahHeap::entry_concurrent_roots() { + ShenandoahGCPhase phase(ShenandoahPhaseTimings::conc_roots); + + static const char* msg = "Concurrent roots processing"; + GCTraceTime(Info, gc) time(msg, NULL, GCCause::_no_gc, true); + EventMark em("%s", msg); + + ShenandoahWorkerScope scope(workers(), + ShenandoahWorkerPolicy::calc_workers_for_conc_root_processing(), + "concurrent root processing"); + + try_inject_alloc_failure(); + op_concurrent_roots(); +} + void ShenandoahHeap::entry_cleanup() { ShenandoahGCPhase phase(ShenandoahPhaseTimings::conc_cleanup);