diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp index c3797e21746..32d9050fcc8 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp @@ -342,7 +342,11 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, #endif Address gc_state(thread, in_bytes(ShenandoahThreadLocalData::gc_state_offset())); - __ testb(gc_state, ShenandoahHeap::HAS_FORWARDED); + int flags = ShenandoahHeap::HAS_FORWARDED; + if (!is_strong) { + flags |= ShenandoahHeap::WEAK_ROOTS; + } + __ testb(gc_state, flags); __ jcc(Assembler::zero, heap_stable); Register tmp1 = noreg, tmp2 = noreg; diff --git a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp index 1478d64e5ef..97041ee1743 100644 --- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp +++ b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp @@ -138,7 +138,11 @@ LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier_impl(LIRGenerator* gen, L // Read and check the gc-state-flag. LIR_Opr flag_val = gen->new_register(T_INT); __ load(active_flag_addr, flag_val); - LIR_Opr mask = LIR_OprFact::intConst(ShenandoahHeap::HAS_FORWARDED); + int flags = ShenandoahHeap::HAS_FORWARDED; + if (!ShenandoahBarrierSet::is_strong_access(decorators)) { + flags |= ShenandoahHeap::WEAK_ROOTS; + } + LIR_Opr mask = LIR_OprFact::intConst(flags); LIR_Opr mask_reg = gen->new_register(T_INT); __ move(mask, mask_reg); diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index 8a06f51e16c..97d2882bf5a 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -1362,7 +1362,11 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) { Node* raw_mem_phi = PhiNode::make(region, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM); // Stable path. - test_gc_state(ctrl, raw_mem, heap_stable_ctrl, phase, ShenandoahHeap::HAS_FORWARDED); + int flags = ShenandoahHeap::HAS_FORWARDED; + if (!ShenandoahBarrierSet::is_strong_access(lrb->decorators())) { + flags |= ShenandoahHeap::WEAK_ROOTS; + } + test_gc_state(ctrl, raw_mem, heap_stable_ctrl, phase, flags); IfNode* heap_stable_iff = heap_stable_ctrl->in(0)->as_If(); // Heap stable case diff --git a/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp b/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp index cf97e06e011..52d04a33b8a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp @@ -140,12 +140,6 @@ class ShenandoahCodeBlobAndDisarmClosure: public CodeBlobToOopClosure { inline void do_code_blob(CodeBlob* cb); }; -class ShenandoahRendezvousClosure : public HandshakeClosure { -public: - inline ShenandoahRendezvousClosure(); - inline void do_thread(Thread* thread); -}; - #ifdef ASSERT class ShenandoahAssertNotForwardedClosure : public OopClosure { private: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp index 79dd8feaa95..e6e219f7400 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp @@ -233,13 +233,6 @@ void ShenandoahCodeBlobAndDisarmClosure::do_code_blob(CodeBlob* cb) { } } -ShenandoahRendezvousClosure::ShenandoahRendezvousClosure() : - HandshakeClosure("ShenandoahRendezvous") { -} - -void ShenandoahRendezvousClosure::do_thread(Thread* thread) { -} - #ifdef ASSERT template void ShenandoahAssertNotForwardedClosure::do_oop_work(T* p) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index 8982a4e2309..16df11fe439 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -166,11 +166,7 @@ bool ShenandoahConcurrentGC::collect(GCCause::Cause cause) { // Update references freed up collection set, kick the cleanup to reclaim the space. entry_cleanup_complete(); } else { - // Concurrent weak/strong root flags are unset concurrently. We depend on updateref GC safepoints - // to ensure the changes are visible to all mutators before gc cycle is completed. - // In case of no evacuation, updateref GC safepoints are skipped. Therefore, we will need - // to perform thread handshake to ensure their consistences. - entry_rendezvous_roots(); + vmop_entry_final_roots(); } return true; @@ -216,6 +212,17 @@ void ShenandoahConcurrentGC::vmop_entry_final_updaterefs() { VMThread::execute(&op); } +void ShenandoahConcurrentGC::vmop_entry_final_roots() { + ShenandoahHeap* const heap = ShenandoahHeap::heap(); + TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters()); + ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_roots_gross); + + // This phase does not use workers, no need for setup + heap->try_inject_alloc_failure(); + VM_ShenandoahFinalRoots op(this); + VMThread::execute(&op); +} + void ShenandoahConcurrentGC::entry_init_mark() { const char* msg = init_mark_event_message(); ShenandoahPausePhase gc_phase(msg, ShenandoahPhaseTimings::init_mark); @@ -261,6 +268,14 @@ void ShenandoahConcurrentGC::entry_final_updaterefs() { op_final_updaterefs(); } +void ShenandoahConcurrentGC::entry_final_roots() { + static const char* msg = "Pause Final Roots"; + ShenandoahPausePhase gc_phase(msg, ShenandoahPhaseTimings::final_roots); + EventMark em("%s", msg); + + op_final_roots(); +} + void ShenandoahConcurrentGC::entry_reset() { ShenandoahHeap* const heap = ShenandoahHeap::heap(); TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters()); @@ -393,18 +408,6 @@ void ShenandoahConcurrentGC::entry_cleanup_early() { op_cleanup_early(); } -void ShenandoahConcurrentGC::entry_rendezvous_roots() { - ShenandoahHeap* const heap = ShenandoahHeap::heap(); - TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters()); - static const char* msg = "Rendezvous roots"; - ShenandoahConcurrentPhase gc_phase(msg, ShenandoahPhaseTimings::conc_rendezvous_roots); - EventMark em("%s", msg); - - // This phase does not use workers, no need for setup - heap->try_inject_alloc_failure(); - op_rendezvous_roots(); -} - void ShenandoahConcurrentGC::entry_evacuate() { ShenandoahHeap* const heap = ShenandoahHeap::heap(); TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters()); @@ -804,16 +807,6 @@ void ShenandoahConcurrentGC::op_weak_roots() { ShenandoahConcurrentWeakRootsEvacUpdateTask task(ShenandoahPhaseTimings::conc_weak_roots_work); heap->workers()->run_task(&task); } - - // Perform handshake to flush out dead oops - { - ShenandoahTimingsTracker t(ShenandoahPhaseTimings::conc_weak_roots_rendezvous); - heap->rendezvous_threads(); - } - - if (!ShenandoahHeap::heap()->unload_classes()) { - heap->set_concurrent_weak_root_in_progress(false); - } } void ShenandoahConcurrentGC::op_class_unloading() { @@ -822,7 +815,6 @@ void ShenandoahConcurrentGC::op_class_unloading() { heap->unload_classes(), "Checked by caller"); heap->do_class_unloading(); - heap->set_concurrent_weak_root_in_progress(false); } class ShenandoahEvacUpdateCodeCacheClosure : public NMethodClosure { @@ -913,10 +905,6 @@ void ShenandoahConcurrentGC::op_cleanup_early() { ShenandoahHeap::heap()->free_set()->recycle_trash(); } -void ShenandoahConcurrentGC::op_rendezvous_roots() { - ShenandoahHeap::heap()->rendezvous_threads(); -} - void ShenandoahConcurrentGC::op_evacuate() { ShenandoahHeap::heap()->evacuate_collection_set(true /*concurrent*/); } @@ -924,6 +912,7 @@ void ShenandoahConcurrentGC::op_evacuate() { void ShenandoahConcurrentGC::op_init_updaterefs() { ShenandoahHeap* const heap = ShenandoahHeap::heap(); heap->set_evacuation_in_progress(false); + heap->set_concurrent_weak_root_in_progress(false); heap->prepare_update_heap_references(true /*concurrent*/); heap->set_update_refs_in_progress(true); @@ -995,6 +984,10 @@ void ShenandoahConcurrentGC::op_final_updaterefs() { heap->rebuild_free_set(true /*concurrent*/); } +void ShenandoahConcurrentGC::op_final_roots() { + ShenandoahHeap::heap()->set_concurrent_weak_root_in_progress(false); +} + void ShenandoahConcurrentGC::op_cleanup_complete() { ShenandoahHeap::heap()->free_set()->recycle_trash(); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp index 8283c541326..6f83d980f05 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp @@ -40,6 +40,7 @@ class ShenandoahConcurrentGC : public ShenandoahGC { friend class VM_ShenandoahFinalMarkStartEvac; friend class VM_ShenandoahInitUpdateRefs; friend class VM_ShenandoahFinalUpdateRefs; + friend class VM_ShenandoahFinalRoots; private: ShenandoahConcurrentMark _mark; @@ -59,6 +60,7 @@ class ShenandoahConcurrentGC : public ShenandoahGC { void vmop_entry_final_mark(); void vmop_entry_init_updaterefs(); void vmop_entry_final_updaterefs(); + void vmop_entry_final_roots(); // Entry methods to normally STW GC operations. These set up logging, monitoring // and workers for net VM operation @@ -66,6 +68,7 @@ class ShenandoahConcurrentGC : public ShenandoahGC { void entry_final_mark(); void entry_init_updaterefs(); void entry_final_updaterefs(); + void entry_final_roots(); // Entry methods to normally concurrent GC operations. These set up logging, monitoring // for concurrent operation. @@ -78,7 +81,6 @@ class ShenandoahConcurrentGC : public ShenandoahGC { void entry_class_unloading(); void entry_strong_roots(); void entry_cleanup_early(); - void entry_rendezvous_roots(); void entry_evacuate(); void entry_update_thread_roots(); void entry_updaterefs(); @@ -96,12 +98,12 @@ class ShenandoahConcurrentGC : public ShenandoahGC { void op_class_unloading(); void op_strong_roots(); void op_cleanup_early(); - void op_rendezvous_roots(); void op_evacuate(); void op_init_updaterefs(); void op_updaterefs(); void op_update_thread_roots(); void op_final_updaterefs(); + void op_final_roots(); void op_cleanup_complete(); // Messages for GC trace events, they have to be immortal for diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp index e54feb68298..5769c120994 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp @@ -124,10 +124,8 @@ void ShenandoahFullGC::do_it(GCCause::Cause gc_cause) { // Degenerated GC may carry concurrent root flags when upgrading to // full GC. We need to reset it before mutators resume. - if (ClassUnloading) { - heap->set_concurrent_strong_root_in_progress(false); - heap->set_concurrent_weak_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); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index ffca19b3a20..68f1a758351 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -1545,11 +1545,6 @@ class ShenandoahInitMarkUpdateRegionStateClosure : public ShenandoahHeapRegionCl bool is_thread_safe() { return true; } }; -void ShenandoahHeap::rendezvous_threads() { - ShenandoahRendezvousClosure cl; - Handshake::execute(&cl); -} - void ShenandoahHeap::recycle_trash() { free_set()->recycle_trash(); } @@ -1655,7 +1650,6 @@ void ShenandoahHeap::prepare_regions_and_collection_set(bool concurrent) { void ShenandoahHeap::do_class_unloading() { _unloader.unload(); - set_concurrent_weak_root_in_progress(false); } void ShenandoahHeap::stw_weak_refs(bool full_gc) { @@ -1714,12 +1708,8 @@ void ShenandoahHeap::set_concurrent_strong_root_in_progress(bool in_progress) { } } -void ShenandoahHeap::set_concurrent_weak_root_in_progress(bool in_progress) { - if (in_progress) { - _concurrent_weak_root_in_progress.set(); - } else { - _concurrent_weak_root_in_progress.unset(); - } +void ShenandoahHeap::set_concurrent_weak_root_in_progress(bool cond) { + set_gc_state_mask(WEAK_ROOTS, cond); } GCTracer* ShenandoahHeap::tracer() { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index d0dda89a9e9..a4c5e298cd7 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -263,6 +263,9 @@ class ShenandoahHeap : public CollectedHeap { // Heap is under updating: needs no additional barriers. UPDATEREFS_BITPOS = 3, + + // Heap is under weak-reference/roots processing: needs weak-LRB barriers. + WEAK_ROOTS_BITPOS = 4, }; enum GCState { @@ -271,6 +274,7 @@ class ShenandoahHeap : public CollectedHeap { MARKING = 1 << MARKING_BITPOS, EVACUATION = 1 << EVACUATION_BITPOS, UPDATEREFS = 1 << UPDATEREFS_BITPOS, + WEAK_ROOTS = 1 << WEAK_ROOTS_BITPOS, }; private: @@ -280,7 +284,6 @@ class ShenandoahHeap : public CollectedHeap { ShenandoahSharedFlag _full_gc_move_in_progress; ShenandoahSharedFlag _progress_last_gc; ShenandoahSharedFlag _concurrent_strong_root_in_progress; - ShenandoahSharedFlag _concurrent_weak_root_in_progress; void set_gc_state_all_threads(char state); void set_gc_state_mask(uint mask, bool value); @@ -367,7 +370,6 @@ class ShenandoahHeap : public CollectedHeap { void update_heap_region_states(bool concurrent); void rebuild_free_set(bool concurrent); - void rendezvous_threads(); void recycle_trash(); public: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp index c39737c15b8..8d116005804 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp @@ -340,7 +340,7 @@ inline bool ShenandoahHeap::is_concurrent_strong_root_in_progress() const { } inline bool ShenandoahHeap::is_concurrent_weak_root_in_progress() const { - return _concurrent_weak_root_in_progress.is_set(); + return _gc_state.is_set(WEAK_ROOTS); } template diff --git a/src/hotspot/share/gc/shenandoah/shenandoahNMethod.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahNMethod.inline.hpp index 9260e0a0bd4..ce84544dba8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahNMethod.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahNMethod.inline.hpp @@ -28,6 +28,7 @@ #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetNMethod.hpp" #include "gc/shenandoah/shenandoahNMethod.hpp" +#include "gc/shenandoah/shenandoahClosures.inline.hpp" nmethod* ShenandoahNMethod::nm() const { return _nm; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp index 8d411891dcf..c9d41e6d294 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp @@ -82,7 +82,6 @@ class outputStream; f(conc_weak_roots, "Concurrent Weak Roots") \ f(conc_weak_roots_work, " Roots") \ SHENANDOAH_PAR_PHASE_DO(conc_weak_roots_work_, " CWR: ", f) \ - f(conc_weak_roots_rendezvous, " Rendezvous") \ f(conc_cleanup_early, "Concurrent Cleanup") \ f(conc_class_unload, "Concurrent Class Unloading") \ f(conc_class_unload_unlink, " Unlink Stale") \ @@ -96,9 +95,11 @@ class outputStream; f(conc_class_unload_purge_ec, " Exception Caches") \ f(conc_strong_roots, "Concurrent Strong Roots") \ SHENANDOAH_PAR_PHASE_DO(conc_strong_roots_, " CSR: ", f) \ - f(conc_rendezvous_roots, "Rendezvous") \ f(conc_evac, "Concurrent Evacuation") \ \ + f(final_roots_gross, "Pause Final Roots (G)") \ + f(final_roots, "Pause Final Roots (N)") \ + \ f(init_update_refs_gross, "Pause Init Update Refs (G)") \ f(init_update_refs, "Pause Init Update Refs (N)") \ f(init_update_refs_manage_gclabs, " Manage GCLABs") \ diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp index ac835d55f6a..c4160999d26 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp @@ -46,13 +46,11 @@ ShenandoahGCStateResetter::ShenandoahGCStateResetter() : _gc_state(_heap->gc_state()), _concurrent_weak_root_in_progress(ShenandoahHeap::heap()->is_concurrent_weak_root_in_progress()) { _heap->_gc_state.clear(); - _heap->set_concurrent_weak_root_in_progress(false); } ShenandoahGCStateResetter::~ShenandoahGCStateResetter() { _heap->_gc_state.set(_gc_state); assert(_heap->gc_state() == _gc_state, "Should be restored"); - _heap->set_concurrent_weak_root_in_progress(_concurrent_weak_root_in_progress); } void ShenandoahRootVerifier::roots_do(OopClosure* oops) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp b/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp index dc7af9cbeba..6df1246431a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp @@ -31,8 +31,6 @@ #include "code/dependencyContext.hpp" #include "gc/shared/gcBehaviours.hpp" #include "gc/shared/suspendibleThreadSet.hpp" -#include "gc/shenandoah/shenandoahClosures.inline.hpp" -#include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahNMethod.inline.hpp" #include "gc/shenandoah/shenandoahLock.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" @@ -135,6 +133,12 @@ void ShenandoahUnload::prepare() { DependencyContext::cleaning_start(); } +class ShenandoahRendezvousClosure : public HandshakeClosure { +public: + inline ShenandoahRendezvousClosure() : HandshakeClosure("ShenandoahRendezvous") {} + inline void do_thread(Thread* thread) {} +}; + void ShenandoahUnload::unload() { ShenandoahHeap* heap = ShenandoahHeap::heap(); assert(ClassUnloading, "Filtered by caller"); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp index 20ff5000246..49ff6ca2864 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp @@ -165,6 +165,7 @@ class ShenandoahSafepoint : public AllStatic { type == VM_Operation::VMOp_ShenandoahFinalMarkStartEvac || type == VM_Operation::VMOp_ShenandoahInitUpdateRefs || type == VM_Operation::VMOp_ShenandoahFinalUpdateRefs || + type == VM_Operation::VMOp_ShenandoahFinalRoots || type == VM_Operation::VMOp_ShenandoahFullGC || type == VM_Operation::VMOp_ShenandoahDegeneratedGC; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.cpp index d666d55a9be..18bd4d6e6aa 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.cpp @@ -75,3 +75,8 @@ void VM_ShenandoahFinalUpdateRefs::doit() { ShenandoahGCPauseMark mark(_gc_id, SvcGCMarker::CONCURRENT); _gc->entry_final_updaterefs(); } + +void VM_ShenandoahFinalRoots::doit() { + ShenandoahGCPauseMark mark(_gc_id, SvcGCMarker::CONCURRENT); + _gc->entry_final_roots(); +} diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.hpp b/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.hpp index fd58c92ee9b..65ddd8b1f11 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.hpp @@ -130,4 +130,15 @@ class VM_ShenandoahFinalUpdateRefs: public VM_ShenandoahOperation { virtual void doit(); }; +class VM_ShenandoahFinalRoots: public VM_ShenandoahOperation { + ShenandoahConcurrentGC* const _gc; +public: + VM_ShenandoahFinalRoots(ShenandoahConcurrentGC* gc) : + VM_ShenandoahOperation(), + _gc(gc) {}; + VM_Operation::VMOp_Type type() const { return VMOp_ShenandoahFinalRoots; } + const char* name() const { return "Shenandoah Final Roots"; } + virtual void doit(); +}; + #endif // SHARE_GC_SHENANDOAH_SHENANDOAHVMOPERATIONS_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp index 0fd315ce8dd..e309cdebe07 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp @@ -639,11 +639,23 @@ void ShenandoahVerifier::verify_at_safepoint(const char *label, case _verify_gcstate_evacuation: enabled = true; expected = ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::EVACUATION; + if (!_heap->is_stw_gc_in_progress()) { + // Only concurrent GC sets this. + expected |= ShenandoahHeap::WEAK_ROOTS; + } break; case _verify_gcstate_stable: enabled = true; expected = ShenandoahHeap::STABLE; break; + case _verify_gcstate_stable_weakroots: + enabled = true; + expected = ShenandoahHeap::STABLE; + if (!_heap->is_stw_gc_in_progress()) { + // Only concurrent GC sets this. + expected |= ShenandoahHeap::WEAK_ROOTS; + } + break; default: enabled = false; assert(false, "Unhandled gc-state verification"); @@ -799,7 +811,7 @@ void ShenandoahVerifier::verify_after_concmark() { _verify_cset_none, // no references to cset anymore _verify_liveness_complete, // liveness data must be complete here _verify_regions_disable, // trash regions not yet recycled - _verify_gcstate_stable // mark should have stabilized the heap + _verify_gcstate_stable_weakroots // heap is still stable, weakroots are in progress ); } @@ -811,7 +823,7 @@ void ShenandoahVerifier::verify_before_evacuation() { _verify_cset_disable, // non-forwarded references to cset expected _verify_liveness_complete, // liveness data must be complete here _verify_regions_disable, // trash regions not yet recycled - _verify_gcstate_stable // mark should have stabilized the heap + _verify_gcstate_stable_weakroots // heap is still stable, weakroots are in progress ); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp index 9c9cd6117d5..d74f46c745a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp @@ -129,6 +129,9 @@ class ShenandoahVerifier : public CHeapObj { // Nothing is in progress, no forwarded objects _verify_gcstate_stable, + // Nothing is in progress, no forwarded objects, weak roots handling + _verify_gcstate_stable_weakroots, + // Nothing is in progress, some objects are forwarded _verify_gcstate_forwarded, diff --git a/src/hotspot/share/runtime/vmOperation.hpp b/src/hotspot/share/runtime/vmOperation.hpp index 4e41eb5dcbb..1fe9a60841e 100644 --- a/src/hotspot/share/runtime/vmOperation.hpp +++ b/src/hotspot/share/runtime/vmOperation.hpp @@ -88,6 +88,7 @@ template(ShenandoahFinalMarkStartEvac) \ template(ShenandoahInitUpdateRefs) \ template(ShenandoahFinalUpdateRefs) \ + template(ShenandoahFinalRoots) \ template(ShenandoahDegeneratedGC) \ template(Exit) \ template(LinuxDllLoad) \ diff --git a/test/hotspot/jtreg/gc/shenandoah/TestReferenceRefersToShenandoah.java b/test/hotspot/jtreg/gc/shenandoah/TestReferenceRefersToShenandoah.java index 40ecac086ff..4ea94f29c88 100644 --- a/test/hotspot/jtreg/gc/shenandoah/TestReferenceRefersToShenandoah.java +++ b/test/hotspot/jtreg/gc/shenandoah/TestReferenceRefersToShenandoah.java @@ -47,6 +47,32 @@ * gc.shenandoah.TestReferenceRefersToShenandoah */ +/* @test + * @requires vm.gc.Shenandoah + * @library /test/lib + * @build sun.hotspot.WhiteBox + * @modules java.base + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm + * -Xbootclasspath/a:. + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=satb -XX:ShenandoahGarbageThreshold=100 -Xmx100m + * gc.shenandoah.TestReferenceRefersToShenandoah + */ + +/* @test + * @requires vm.gc.Shenandoah + * @library /test/lib + * @build sun.hotspot.WhiteBox + * @modules java.base + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm + * -Xbootclasspath/a:. + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=iu -XX:ShenandoahGarbageThreshold=100 -Xmx100m + * gc.shenandoah.TestReferenceRefersToShenandoah + */ + import java.lang.ref.PhantomReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; diff --git a/test/hotspot/jtreg/gc/shenandoah/TestReferenceShortcutCycle.java b/test/hotspot/jtreg/gc/shenandoah/TestReferenceShortcutCycle.java new file mode 100644 index 00000000000..4e388d15408 --- /dev/null +++ b/test/hotspot/jtreg/gc/shenandoah/TestReferenceShortcutCycle.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package gc.shenandoah; + +/* @test + * @requires vm.gc.Shenandoah + * @library /test/lib + * @build sun.hotspot.WhiteBox + * @modules java.base + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm + * -Xbootclasspath/a:. + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=satb -XX:ShenandoahGarbageThreshold=100 -Xmx100m + * gc.shenandoah.TestReferenceShortcutCycle + */ + +/* @test + * @requires vm.gc.Shenandoah + * @library /test/lib + * @build sun.hotspot.WhiteBox + * @modules java.base + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm + * -Xbootclasspath/a:. + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=iu -XX:ShenandoahGarbageThreshold=100 -Xmx100m + * gc.shenandoah.TestReferenceShortcutCycle + */ + +import java.lang.ref.PhantomReference; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import sun.hotspot.WhiteBox; + +public class TestReferenceShortcutCycle { + private static final int NUM_ITEMS = 100000; + + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + private static final class TestObject { + public final int value; + + public TestObject(int value) { + this.value = value; + } + } + + private static WeakReference[] refs; + + private static void setup() { + refs = new WeakReference[NUM_ITEMS]; + for (int i = 0; i < NUM_ITEMS; i++) { + refs[i] = new WeakReference<>(new TestObject(i)); + } + } + + private static void fail(String msg) throws Exception { + throw new RuntimeException(msg); + } + + private static void testConcurrentCollection() throws Exception { + setup(); + WB.concurrentGCAcquireControl(); + try { + WB.concurrentGCRunToIdle(); + WB.concurrentGCRunTo(WB.AFTER_CONCURRENT_REFERENCE_PROCESSING_STARTED); + for (int i = 0; i < NUM_ITEMS; i++) { + if (refs[i].get() != null) { + fail("resurrected referent"); + } + } + } finally { + WB.concurrentGCReleaseControl(); + } + } + public static void main(String[] args) throws Exception { + testConcurrentCollection(); + } +}