--- old/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp 2019-06-11 20:26:13.911680010 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp 2019-06-11 20:26:13.490679261 -0400 @@ -156,7 +156,7 @@ void work(uint worker_id) { ShenandoahHeap* heap = ShenandoahHeap::heap(); ShenandoahConcurrentWorkerSession worker_session(worker_id); - ShenandoahSuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers); + ShenandoahSuspendibleThreadSetJoiner stsj; ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id); ReferenceProcessor* rp; if (heap->process_references()) { @@ -982,7 +982,7 @@ if (work == 0) { // No work encountered in current stride, try to terminate. // Need to leave the STS here otherwise it might block safepoints. - ShenandoahSuspendibleThreadSetLeaver stsl(CANCELLABLE && ShenandoahSuspendibleWorkers); + ShenandoahSuspendibleThreadSetLeaver stsl(CANCELLABLE); ShenandoahTerminationTimingsTracker term_tracker(worker_id); ShenandoahTerminatorTerminator tt(heap); if (terminator->offer_termination(&tt)) return; --- old/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp 2019-06-11 20:26:14.981681912 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp 2019-06-11 20:26:14.527681105 -0400 @@ -377,6 +377,9 @@ // Complete marking under STW, and start evacuation heap->vmop_entry_final_mark(); + // Evacuate concurrent roots + heap->entry_concurrent_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. heap->entry_cleanup(); --- 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); --- old/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp 2019-06-11 20:26:17.072685629 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp 2019-06-11 20:26:16.601684791 -0400 @@ -391,6 +391,7 @@ void entry_reset(); void entry_mark(); void entry_preclean(); + void entry_concurrent_roots(); void entry_cleanup(); void entry_evac(); void entry_updaterefs(); @@ -414,6 +415,7 @@ void op_reset(); void op_mark(); void op_preclean(); + void op_concurrent_roots(); void op_cleanup(); void op_conc_evac(); void op_stw_evac(); --- old/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp 2019-06-11 20:26:18.352687904 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp 2019-06-11 20:26:17.780686887 -0400 @@ -187,7 +187,7 @@ } inline bool ShenandoahHeap::check_cancelled_gc_and_yield(bool sts_active) { - if (! (sts_active && ShenandoahSuspendibleWorkers)) { + if (!sts_active) { return cancelled_gc(); } --- old/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp 2019-06-11 20:26:19.660690229 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp 2019-06-11 20:26:19.089689214 -0400 @@ -306,6 +306,7 @@ f(conc_mark, "Concurrent Marking") \ f(conc_termination, " Termination") \ f(conc_preclean, "Concurrent Precleaning") \ + f(conc_roots, "Concurrent Roots") \ f(conc_evac, "Concurrent Evacuation") \ f(conc_update_refs, "Concurrent Update Refs") \ f(conc_cleanup, "Concurrent Cleanup") \ --- old/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp 2019-06-11 20:26:20.931692489 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp 2019-06-11 20:26:20.428691594 -0400 @@ -71,10 +71,6 @@ _jvmti_root.oops_do(cl, worker_id); } -ShenandoahJNIHandleRoots::ShenandoahJNIHandleRoots() : - ShenandoahSerialRoot(&JNIHandles::oops_do, ShenandoahPhaseTimings::JNIRoots) { -} - ShenandoahThreadRoots::ShenandoahThreadRoots(bool is_par) : _is_par(is_par) { Threads::change_thread_claim_token(); } @@ -126,22 +122,6 @@ } } -ShenandoahClassLoaderDataRoots::ShenandoahClassLoaderDataRoots() { - ClassLoaderDataGraph::clear_claimed_marks(); -} - -void ShenandoahClassLoaderDataRoots::always_strong_cld_do(CLDClosure* clds, uint worker_id) { - ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id); - ClassLoaderDataGraph::always_strong_cld_do(clds); -} - -void ShenandoahClassLoaderDataRoots::cld_do(CLDClosure* clds, uint worker_id) { - ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id); - ClassLoaderDataGraph::cld_do(clds); -} - ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase) : _heap(ShenandoahHeap::heap()), _phase(phase) { @@ -154,24 +134,25 @@ _heap->phase_timings()->record_workers_end(_phase); } -ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase) : +ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool include_concurrent_roots) : ShenandoahRootProcessor(phase), _thread_roots(n_workers > 1), - _weak_roots(n_workers) { + _weak_roots(n_workers), + _include_concurrent_roots(include_concurrent_roots) { } void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) { MarkingCodeBlobClosure blobsCl(oops, CodeBlobToOopClosure::FixRelocations); - CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong); - CLDToOopClosure* weak_clds = ShenandoahHeap::heap()->unload_classes() ? NULL : &clds; - AlwaysTrueClosure always_true; _serial_roots.oops_do(oops, worker_id); - _jni_roots.oops_do(oops, worker_id); + if (_include_concurrent_roots) { + CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong); + _jni_roots.oops_do(oops, worker_id); + _cld_roots.cld_do(&clds, worker_id); + } _thread_roots.oops_do(oops, NULL, worker_id); - _cld_roots.cld_do(&clds, worker_id); _code_roots.code_blobs_do(&blobsCl, worker_id); _weak_roots.oops_do(&always_true, oops, worker_id); --- old/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp 2019-06-11 20:26:22.253694838 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp 2019-06-11 20:26:21.743693932 -0400 @@ -61,9 +61,16 @@ void oops_do(OopClosure* cl, uint worker_id); }; -class ShenandoahJNIHandleRoots : public ShenandoahSerialRoot { +template +class ShenandoahJNIHandleRoots { +private: + volatile bool _claimed; + OopStorage::ParState _itr; public: ShenandoahJNIHandleRoots(); + + template + void oops_do(T* cl, uint worker_id = 0); }; class ShenandoahThreadRoots { @@ -108,12 +115,14 @@ void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id); }; +template class ShenandoahClassLoaderDataRoots { public: ShenandoahClassLoaderDataRoots(); + ~ShenandoahClassLoaderDataRoots(); - void always_strong_cld_do(CLDClosure* clds, uint worker_id); - void cld_do(CLDClosure* clds, uint worker_id); + void always_strong_cld_do(CLDClosure* clds, uint worker_id = 0); + void cld_do(CLDClosure* clds, uint worker_id = 0); }; class ShenandoahRootProcessor : public StackObj { @@ -130,11 +139,11 @@ template class ShenandoahRootScanner : public ShenandoahRootProcessor { private: - ShenandoahSerialRoots _serial_roots; - ShenandoahJNIHandleRoots _jni_roots; - ShenandoahClassLoaderDataRoots _cld_roots; - ShenandoahThreadRoots _thread_roots; - ShenandoahCodeCacheRoots _code_roots; + ShenandoahSerialRoots _serial_roots; + ShenandoahJNIHandleRoots<> _jni_roots; + ShenandoahClassLoaderDataRoots<> _cld_roots; + ShenandoahThreadRoots _thread_roots; + ShenandoahCodeCacheRoots _code_roots; public: ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase); @@ -158,16 +167,17 @@ // Evacuate all roots at a safepoint class ShenandoahRootEvacuator : public ShenandoahRootProcessor { private: - ShenandoahSerialRoots _serial_roots; - ShenandoahJNIHandleRoots _jni_roots; - ShenandoahClassLoaderDataRoots _cld_roots; - ShenandoahThreadRoots _thread_roots; - ShenandoahWeakRoots _weak_roots; - ShenandoahStringDedupRoots _dedup_roots; + ShenandoahSerialRoots _serial_roots; + ShenandoahJNIHandleRoots<> _jni_roots; + ShenandoahClassLoaderDataRoots<> _cld_roots; + ShenandoahThreadRoots _thread_roots; + ShenandoahWeakRoots _weak_roots; + ShenandoahStringDedupRoots _dedup_roots; ShenandoahCodeCacheRoots _code_roots; + bool _include_concurrent_roots; public: - ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase); + ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool include_concurrent_roots); void roots_do(uint worker_id, OopClosure* oops); }; @@ -175,14 +185,14 @@ // Update all roots at a safepoint class ShenandoahRootUpdater : public ShenandoahRootProcessor { private: - ShenandoahSerialRoots _serial_roots; - ShenandoahJNIHandleRoots _jni_roots; - ShenandoahClassLoaderDataRoots _cld_roots; - ShenandoahThreadRoots _thread_roots; - ShenandoahWeakRoots _weak_roots; - ShenandoahStringDedupRoots _dedup_roots; + ShenandoahSerialRoots _serial_roots; + ShenandoahJNIHandleRoots<> _jni_roots; + ShenandoahClassLoaderDataRoots<> _cld_roots; + ShenandoahThreadRoots _thread_roots; + ShenandoahWeakRoots _weak_roots; + ShenandoahStringDedupRoots _dedup_roots; ShenandoahCodeCacheRoots _code_roots; - const bool _update_code_cache; + const bool _update_code_cache; public: ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool update_code_cache); @@ -194,12 +204,12 @@ // Adjuster all roots at a safepoint during full gc class ShenandoahRootAdjuster : public ShenandoahRootProcessor { private: - ShenandoahSerialRoots _serial_roots; - ShenandoahJNIHandleRoots _jni_roots; - ShenandoahClassLoaderDataRoots _cld_roots; - ShenandoahThreadRoots _thread_roots; - ShenandoahWeakRoots _weak_roots; - ShenandoahStringDedupRoots _dedup_roots; + ShenandoahSerialRoots _serial_roots; + ShenandoahJNIHandleRoots<> _jni_roots; + ShenandoahClassLoaderDataRoots<> _cld_roots; + ShenandoahThreadRoots _thread_roots; + ShenandoahWeakRoots _weak_roots; + ShenandoahStringDedupRoots _dedup_roots; ShenandoahCodeCacheRoots _code_roots; public: --- old/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp 2019-06-11 20:26:23.606697244 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp 2019-06-11 20:26:23.076696301 -0400 @@ -24,17 +24,76 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP +#include "classfile/classLoaderDataGraph.hpp" +#include "gc/shared/oopStorageParState.inline.hpp" #include "gc/shenandoah/shenandoahHeuristics.hpp" #include "gc/shenandoah/shenandoahRootProcessor.hpp" #include "gc/shenandoah/shenandoahTimingTracker.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "memory/resourceArea.hpp" +template +ShenandoahJNIHandleRoots::ShenandoahJNIHandleRoots() : + _claimed(false), + _itr(JNIHandles::global_handles()) { +} + +template +template +void ShenandoahJNIHandleRoots::oops_do(T* cl, uint worker_id) { + if (CONCURRENT) { + _itr.oops_do(cl); + } else { + if (!_claimed && Atomic::cmpxchg(true, &_claimed, false) == false) { + ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); + ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JNIRoots, worker_id); + _itr.oops_do(cl); + } + } +} + template void ShenandoahWeakRoots::oops_do(IsAlive* is_alive, KeepAlive* keep_alive, uint worker_id) { _task.work(worker_id, is_alive, keep_alive); } +template +ShenandoahClassLoaderDataRoots::ShenandoahClassLoaderDataRoots() { + ClassLoaderDataGraph::clear_claimed_marks(); + if (CONCURRENT) { + ClassLoaderDataGraph_lock->lock(); + } +} + +template +ShenandoahClassLoaderDataRoots::~ShenandoahClassLoaderDataRoots() { + if (CONCURRENT) { + ClassLoaderDataGraph_lock->unlock(); + } +} + +template +void ShenandoahClassLoaderDataRoots::always_strong_cld_do(CLDClosure* clds, uint worker_id) { + if (CONCURRENT) { + ClassLoaderDataGraph::always_strong_cld_do(clds); + } else { + ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); + ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id); + ClassLoaderDataGraph::always_strong_cld_do(clds); + } +} + +template +void ShenandoahClassLoaderDataRoots::cld_do(CLDClosure* clds, uint worker_id) { + if (CONCURRENT) { + ClassLoaderDataGraph::cld_do(clds); + } else { + ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); + ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id); + ClassLoaderDataGraph::cld_do(clds); + } +} + template ShenandoahCodeCacheRoots::ShenandoahCodeCacheRoots() { nmethod::oops_do_marking_prologue(); --- old/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp 2019-06-11 20:26:24.780699330 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp 2019-06-11 20:26:24.280698442 -0400 @@ -54,6 +54,10 @@ return (_types & type) != 0; } +ShenandoahRootVerifier::RootTypes ShenandoahRootVerifier::combine(RootTypes t1, RootTypes t2) { + return static_cast(static_cast(t1) | static_cast(t2)); +} + void ShenandoahRootVerifier::oops_do(OopClosure* oops) { CodeBlobToOopClosure blobs(oops, !CodeBlobToOopClosure::FixRelocations); if (verify(CodeRoots)) { --- old/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp 2019-06-11 20:26:25.892701307 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp 2019-06-11 20:26:25.428700482 -0400 @@ -52,6 +52,8 @@ // Used to seed ShenandoahVerifier, do not honor root type filter void roots_do(OopClosure* cl); void strong_roots_do(OopClosure* cl); + + static RootTypes combine(RootTypes t1, RootTypes t2); private: bool verify(RootTypes type) const; }; --- old/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp 2019-06-11 20:26:26.985703250 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp 2019-06-11 20:26:26.508702402 -0400 @@ -214,7 +214,7 @@ void work(uint worker_id) { ShenandoahConcurrentWorkerSession worker_session(worker_id); - ShenandoahSuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers); + ShenandoahSuspendibleThreadSetJoiner stsj; ShenandoahEvacOOMScope oom_evac_scope; ShenandoahTraversalGC* traversal_gc = _heap->traversal_gc(); @@ -534,7 +534,7 @@ if (work == 0) { // No more work, try to terminate ShenandoahEvacOOMScopeLeaver oom_scope_leaver; - ShenandoahSuspendibleThreadSetLeaver stsl(sts_yield && ShenandoahSuspendibleWorkers); + ShenandoahSuspendibleThreadSetLeaver stsl(sts_yield); ShenandoahTerminationTimingsTracker term_tracker(worker_id); ShenandoahTerminatorTerminator tt(_heap); @@ -847,7 +847,7 @@ void work(uint worker_id) { assert(worker_id == 0, "The code below is single-threaded, only one worker is expected"); ShenandoahParallelWorkerSession worker_session(worker_id); - ShenandoahSuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers); + ShenandoahSuspendibleThreadSetJoiner stsj; ShenandoahEvacOOMScope oom_evac_scope; ShenandoahHeap* sh = ShenandoahHeap::heap(); --- old/src/hotspot/share/gc/shenandoah/shenandoahWorkerPolicy.cpp 2019-06-11 20:26:28.038705122 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahWorkerPolicy.cpp 2019-06-11 20:26:27.564704279 -0400 @@ -30,6 +30,7 @@ uint ShenandoahWorkerPolicy::_prev_par_marking = 0; uint ShenandoahWorkerPolicy::_prev_conc_marking = 0; uint ShenandoahWorkerPolicy::_prev_conc_evac = 0; +uint ShenandoahWorkerPolicy::_prev_conc_root_proc = 0; uint ShenandoahWorkerPolicy::_prev_fullgc = 0; uint ShenandoahWorkerPolicy::_prev_degengc = 0; uint ShenandoahWorkerPolicy::_prev_stw_traversal = 0; @@ -63,6 +64,16 @@ return _prev_par_marking; } +// Calculate workers for concurrent root processing +uint ShenandoahWorkerPolicy::calc_workers_for_conc_root_processing() { + uint active_workers = (_prev_conc_root_proc == 0) ? ConcGCThreads : _prev_conc_root_proc; + _prev_conc_root_proc = + WorkerPolicy::calc_active_conc_workers(ConcGCThreads, + active_workers, + Threads::number_of_non_daemon_threads()); + return _prev_conc_root_proc; +} + // Calculate workers for concurrent evacuation (concurrent GC) uint ShenandoahWorkerPolicy::calc_workers_for_conc_evac() { uint active_workers = (_prev_conc_evac == 0) ? ConcGCThreads : _prev_conc_evac; --- old/src/hotspot/share/gc/shenandoah/shenandoahWorkerPolicy.hpp 2019-06-11 20:26:29.151707100 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahWorkerPolicy.hpp 2019-06-11 20:26:28.685706272 -0400 @@ -30,6 +30,7 @@ private: static uint _prev_par_marking; static uint _prev_conc_marking; + static uint _prev_conc_root_proc; static uint _prev_conc_evac; static uint _prev_fullgc; static uint _prev_degengc; @@ -50,6 +51,9 @@ // Calculate the number of workers for final marking static uint calc_workers_for_final_marking(); + // Calculate workers for concurrent root processing + static uint calc_workers_for_conc_root_processing(); + // Calculate workers for concurrent evacuation (concurrent GC) static uint calc_workers_for_conc_evac(); --- old/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp 2019-06-11 20:26:30.282709111 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp 2019-06-11 20:26:29.790708236 -0400 @@ -343,9 +343,6 @@ "definitely alive references to avoid dealing with them during " \ "pause.") \ \ - experimental(bool, ShenandoahSuspendibleWorkers, false, \ - "Suspend concurrent GC worker threads at safepoints") \ - \ diagnostic(bool, ShenandoahSATBBarrier, true, \ "Turn on/off SATB barriers in Shenandoah") \ \ --- old/test/hotspot/jtreg/gc/shenandoah/TestAllocObjects.java 2019-06-11 20:26:31.447711182 -0400 +++ new/test/hotspot/jtreg/gc/shenandoah/TestAllocObjects.java 2019-06-11 20:26:30.988710366 -0400 @@ -45,12 +45,6 @@ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=static TestAllocObjects * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=compact TestAllocObjects * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=traversal TestAllocObjects - * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=adaptive -XX:+ShenandoahSuspendibleWorkers TestAllocObjects - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=static -XX:+ShenandoahSuspendibleWorkers TestAllocObjects - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=compact -XX:+ShenandoahSuspendibleWorkers TestAllocObjects - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=traversal -XX:+ShenandoahSuspendibleWorkers TestAllocObjects - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive -XX:+ShenandoahSuspendibleWorkers TestAllocObjects */ import java.util.Random; --- /dev/null 2019-06-03 18:05:13.248999865 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahConcurrentRoots.cpp 2019-06-11 20:26:32.015712191 -0400 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019, Red Hat, Inc. All rights reserved. + * + * 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. + * + */ + +#include "precompiled.hpp" + +#include "gc/shenandoah/shenandoahConcurrentRoots.hpp" +#include "gc/shenandoah/shenandoahHeap.inline.hpp" + +bool ShenandoahConcurrentRoots::can_do_concurrent_roots() { + // Don't support traversal GC at this moment + return !ShenandoahHeap::heap()->is_concurrent_traversal_in_progress(); +} + +bool ShenandoahConcurrentRoots::should_do_concurrent_roots() { + ShenandoahHeap* const heap = ShenandoahHeap::heap(); + bool stw_gc_in_progress = heap->is_full_gc_in_progress() || + heap->is_degenerated_gc_in_progress(); + return can_do_concurrent_roots() && + !stw_gc_in_progress; +} --- /dev/null 2019-06-03 18:05:13.248999865 -0400 +++ new/src/hotspot/share/gc/shenandoah/shenandoahConcurrentRoots.hpp 2019-06-11 20:26:33.139714189 -0400 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019, Red Hat, Inc. All rights reserved. + * + * 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. + * + */ + +#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCONCURRENTROOTS_HPP +#define SHARE_GC_SHENANDOAH_SHENANDOAHCONCURRENTROOTS_HPP + +#include "memory/allocation.hpp" + +class ShenandoahConcurrentRoots : public AllStatic { +public: + // Can GC settings allow concurrent root processing + static bool can_do_concurrent_roots(); + // If current GC cycle can process roots concurrently + static bool should_do_concurrent_roots(); +}; + + +#endif // SHARE_GC_SHENANDOAH_SHENANDOAHCONCURRENTROOTS_HPP