diff -r 01c5097cf1cd src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp Mon Aug 17 11:36:09 2020 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp Mon Aug 17 19:14:37 2020 -0400 @@ -424,6 +424,11 @@ // Update references freed up collection set, kick the cleanup to reclaim the space. heap->entry_cleanup_complete(); + } else { + // concurrent weak/strong root flags are unset concurrently, we depend on init-updateref pause above + // to make them visible to mutators before gc cycle is completed. + // In this case, init-updateref pause is not executed, we need to perform a handshake to complete the cycle. + heap->entry_finish_roots(); } // Cycle is complete diff -r 01c5097cf1cd src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Mon Aug 17 11:36:09 2020 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Mon Aug 17 19:14:37 2020 -0400 @@ -1821,8 +1821,7 @@ // Perform handshake to flush out dead oops { ShenandoahTimingsTracker t(ShenandoahPhaseTimings::conc_weak_roots_rendezvous); - ShenandoahRendezvousClosure cl; - Handshake::execute(&cl); + rendezvous_threads(); } } } @@ -1842,6 +1841,15 @@ set_concurrent_strong_root_in_progress(false); } +void ShenandoahHeap::op_finish_roots() { + rendezvous_threads(); +} + +void ShenandoahHeap::rendezvous_threads() { + ShenandoahRendezvousClosure cl; + Handshake::execute(&cl); +} + class ShenandoahResetUpdateRegionStateClosure : public ShenandoahHeapRegionClosure { private: ShenandoahMarkingContext* const _ctx; @@ -2900,6 +2908,17 @@ op_cleanup_early(); } +void ShenandoahHeap::entry_finish_roots() { + static const char* msg = "Finish Concurrent roots"; + ShenandoahConcurrentPhase gc_phase(msg, ShenandoahPhaseTimings::conc_finish_roots); + EventMark em("%s", msg); + + // This phase does not use workers, no need for setup + + try_inject_alloc_failure(); + op_finish_roots(); +} + void ShenandoahHeap::entry_cleanup_complete() { static const char* msg = "Concurrent cleanup"; ShenandoahConcurrentPhase gc_phase(msg, ShenandoahPhaseTimings::conc_cleanup_complete, true /* log_heap_usage */); diff -r 01c5097cf1cd src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Mon Aug 17 11:36:09 2020 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Mon Aug 17 19:14:37 2020 -0400 @@ -386,6 +386,7 @@ void entry_class_unloading(); void entry_strong_roots(); void entry_cleanup_early(); + void entry_finish_roots(); void entry_evac(); void entry_updaterefs(); void entry_cleanup_complete(); @@ -409,12 +410,15 @@ void op_class_unloading(); void op_strong_roots(); void op_cleanup_early(); + void op_finish_roots(); void op_conc_evac(); void op_stw_evac(); void op_updaterefs(); void op_cleanup_complete(); void op_uncommit(double shrink_before); + void rendezvous_threads(); + // Messages for GC trace events, they have to be immortal for // passing around the logging/tracing systems const char* init_mark_event_message() const; diff -r 01c5097cf1cd src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp Mon Aug 17 11:36:09 2020 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp Mon Aug 17 19:14:37 2020 -0400 @@ -99,6 +99,7 @@ f(conc_class_unload_purge_cldg, " CLDG") \ f(conc_class_unload_purge_ec, " Exception Caches") \ f(conc_strong_roots, "Concurrent Strong Roots") \ + f(conc_finish_roots, "Finish Concurrent Roots") \ SHENANDOAH_PAR_PHASE_DO(conc_strong_roots_, " CSR: ", f) \ f(conc_evac, "Concurrent Evacuation") \ \