# HG changeset patch # User zgu # Date 1558101155 14400 # Node ID ba1eccda54509904374e159a81337f4927355e24 # Parent 23837d614c1783201592d0b55744e9e9df293049 8223774: Shenandoah: Refactor ShenandoahRootProcessor and family Reviewed-by: shade, rkennke diff -r 23837d614c17 -r ba1eccda5450 src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp Fri May 17 12:33:37 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp Fri May 17 09:52:35 2019 -0400 @@ -81,10 +81,10 @@ template class ShenandoahInitMarkRootsTask : public AbstractGangTask { private: - ShenandoahRootProcessor* _rp; + ShenandoahRootScanner* _rp; bool _process_refs; public: - ShenandoahInitMarkRootsTask(ShenandoahRootProcessor* rp, bool process_refs) : + ShenandoahInitMarkRootsTask(ShenandoahRootScanner* rp, bool process_refs) : AbstractGangTask("Shenandoah init mark roots task"), _rp(rp), _process_refs(process_refs) { @@ -115,45 +115,21 @@ // cache, because there could be the case of embedded class/oop in the generated code, // which we will never visit during mark. Without code cache invalidation, as in (a), // we risk executing that code cache blob, and crashing. - // c. With ShenandoahConcurrentScanCodeRoots, we avoid scanning the entire code cache here, - // and instead do that in concurrent phase under the relevant lock. This saves init mark - // pause time. - - CLDToOopClosure clds_cl(oops, ClassLoaderData::_claim_strong); - MarkingCodeBlobClosure blobs_cl(oops, ! CodeBlobToOopClosure::FixRelocations); - - ResourceMark m; if (heap->unload_classes()) { - _rp->process_strong_roots(oops, &clds_cl, &blobs_cl, NULL, worker_id); + _rp->strong_roots_do(worker_id, oops); } else { - if (ShenandoahConcurrentScanCodeRoots) { - CodeBlobClosure* code_blobs = NULL; -#ifdef ASSERT - ShenandoahAssertToSpaceClosure assert_to_space_oops; - CodeBlobToOopClosure assert_to_space(&assert_to_space_oops, !CodeBlobToOopClosure::FixRelocations); - // If conc code cache evac is disabled, code cache should have only to-space ptrs. - // Otherwise, it should have to-space ptrs only if mark does not update refs. - if (!heap->has_forwarded_objects()) { - code_blobs = &assert_to_space; - } -#endif - _rp->process_all_roots(oops, &clds_cl, code_blobs, NULL, worker_id); - } else { - _rp->process_all_roots(oops, &clds_cl, &blobs_cl, NULL, worker_id); - } + _rp->roots_do(worker_id, oops); } } }; class ShenandoahUpdateRootsTask : public AbstractGangTask { private: - ShenandoahRootProcessor* _rp; - const bool _update_code_cache; + ShenandoahRootUpdater* _root_updater; public: - ShenandoahUpdateRootsTask(ShenandoahRootProcessor* rp, bool update_code_cache) : + ShenandoahUpdateRootsTask(ShenandoahRootUpdater* root_updater) : AbstractGangTask("Shenandoah update roots task"), - _rp(rp), - _update_code_cache(update_code_cache) { + _root_updater(root_updater) { } void work(uint worker_id) { @@ -162,22 +138,8 @@ ShenandoahHeap* heap = ShenandoahHeap::heap(); ShenandoahUpdateRefsClosure cl; - CLDToOopClosure cldCl(&cl, ClassLoaderData::_claim_strong); - - CodeBlobClosure* code_blobs; - CodeBlobToOopClosure update_blobs(&cl, CodeBlobToOopClosure::FixRelocations); -#ifdef ASSERT - ShenandoahAssertToSpaceClosure assert_to_space_oops; - CodeBlobToOopClosure assert_to_space(&assert_to_space_oops, !CodeBlobToOopClosure::FixRelocations); -#endif - if (_update_code_cache) { - code_blobs = &update_blobs; - } else { - code_blobs = - DEBUG_ONLY(&assert_to_space) - NOT_DEBUG(NULL); - } - _rp->update_all_roots(&cl, &cldCl, code_blobs, NULL, worker_id); + AlwaysTrueClosure always_true; + _root_updater->roots_do(worker_id, &always_true, &cl); } }; @@ -289,7 +251,7 @@ assert(nworkers <= task_queues()->size(), "Just check"); - ShenandoahRootProcessor root_proc(heap, nworkers, root_phase); + ShenandoahRootScanner root_proc(nworkers, root_phase); TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats()); task_queues()->reserve(nworkers); @@ -333,8 +295,8 @@ uint nworkers = _heap->workers()->active_workers(); - ShenandoahRootProcessor root_proc(_heap, nworkers, root_phase); - ShenandoahUpdateRootsTask update_roots(&root_proc, update_code_cache); + ShenandoahRootUpdater root_updater(nworkers, root_phase, update_code_cache); + ShenandoahUpdateRootsTask update_roots(&root_updater); _heap->workers()->run_task(&update_roots); #if defined(COMPILER2) || INCLUDE_JVMCI diff -r 23837d614c17 -r ba1eccda5450 src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Fri May 17 12:33:37 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Fri May 17 09:52:35 2019 -0400 @@ -52,7 +52,7 @@ #include "gc/shenandoah/shenandoahMonitoringSupport.hpp" #include "gc/shenandoah/shenandoahOopClosures.inline.hpp" #include "gc/shenandoah/shenandoahPacer.inline.hpp" -#include "gc/shenandoah/shenandoahRootProcessor.hpp" +#include "gc/shenandoah/shenandoahRootProcessor.inline.hpp" #include "gc/shenandoah/shenandoahStringDedup.hpp" #include "gc/shenandoah/shenandoahTaskqueue.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" @@ -1111,7 +1111,7 @@ ShenandoahEvacOOMScope oom_evac_scope; ShenandoahEvacuateUpdateRootsClosure cl; MarkingCodeBlobClosure blobsCl(&cl, CodeBlobToOopClosure::FixRelocations); - _rp->process_evacuate_roots(&cl, &blobsCl, worker_id); + _rp->roots_do(worker_id, &cl); } }; @@ -1122,7 +1122,7 @@ assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Only iterate roots while world is stopped"); { - ShenandoahRootEvacuator rp(this, workers()->active_workers(), ShenandoahPhaseTimings::init_evac); + ShenandoahRootEvacuator rp(workers()->active_workers(), ShenandoahPhaseTimings::init_evac); ShenandoahEvacuateUpdateRootsTask roots_task(&rp); workers()->run_task(&roots_task); } @@ -1326,11 +1326,9 @@ Stack oop_stack; // First, we process all GC roots. This populates the work stack with initial objects. - ShenandoahRootProcessor rp(this, 1, ShenandoahPhaseTimings::_num_phases); + ShenandoahRootScanner rp(1, ShenandoahPhaseTimings::_num_phases); ObjectIterateScanRootClosure oops(&_aux_bit_map, &oop_stack); - CLDToOopClosure clds(&oops, ClassLoaderData::_claim_none); - CodeBlobToOopClosure blobs(&oops, false); - rp.process_all_roots(&oops, &clds, &blobs, NULL, 0); + rp.roots_do(0, &oops); // Work through the oop stack to traverse heap. while (! oop_stack.is_empty()) { diff -r 23837d614c17 -r ba1eccda5450 src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp Fri May 17 12:33:37 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp Fri May 17 09:52:35 2019 -0400 @@ -561,22 +561,16 @@ class ShenandoahAdjustRootPointersTask : public AbstractGangTask { private: - ShenandoahRootProcessor* _rp; + ShenandoahRootAdjuster* _rp; public: - ShenandoahAdjustRootPointersTask(ShenandoahRootProcessor* rp) : + ShenandoahAdjustRootPointersTask(ShenandoahRootAdjuster* rp) : AbstractGangTask("Shenandoah Adjust Root Pointers Task"), _rp(rp) {} void work(uint worker_id) { ShenandoahAdjustPointersClosure cl; - CLDToOopClosure adjust_cld_closure(&cl, ClassLoaderData::_claim_strong); - MarkingCodeBlobClosure adjust_code_closure(&cl, - CodeBlobToOopClosure::FixRelocations); - - _rp->update_all_roots(&cl, - &adjust_cld_closure, - &adjust_code_closure, NULL, worker_id); + _rp->roots_do(worker_id, &cl); } }; @@ -592,7 +586,7 @@ #if COMPILER2_OR_JVMCI DerivedPointerTable::clear(); #endif - ShenandoahRootProcessor rp(heap, nworkers, ShenandoahPhaseTimings::full_gc_roots); + ShenandoahRootAdjuster rp(nworkers, ShenandoahPhaseTimings::full_gc_roots); ShenandoahAdjustRootPointersTask task(&rp); workers->run_task(&task); #if COMPILER2_OR_JVMCI diff -r 23837d614c17 -r ba1eccda5450 src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp Fri May 17 12:33:37 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp Fri May 17 09:52:35 2019 -0400 @@ -28,8 +28,9 @@ #include "classfile/systemDictionary.hpp" #include "code/codeCache.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" -#include "gc/shenandoah/shenandoahRootProcessor.hpp" +#include "gc/shenandoah/shenandoahRootProcessor.inline.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" +#include "gc/shenandoah/shenandoahHeuristics.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahStringDedup.hpp" #include "gc/shenandoah/shenandoahTimingTracker.hpp" @@ -43,67 +44,95 @@ #include "runtime/thread.hpp" #include "services/management.hpp" -ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahHeap* heap, uint n_workers, - ShenandoahPhaseTimings::Phase phase) : - _process_strong_tasks(new SubTasksDone(SHENANDOAH_RP_PS_NumElements)), - _srs(n_workers), - _phase(phase), - _coderoots_all_iterator(ShenandoahCodeRoots::iterator()), - _weak_processor_timings(n_workers), - _weak_processor_task(&_weak_processor_timings, n_workers), - _processed_weak_roots(false) { - heap->phase_timings()->record_workers_start(_phase); +ShenandoahSerialRoot::ShenandoahSerialRoot(ShenandoahSerialRoot::OopsDo oops_do, ShenandoahPhaseTimings::GCParPhases phase) : + _claimed(false), _oops_do(oops_do), _phase(phase) { +} + +void ShenandoahSerialRoot::oops_do(OopClosure* cl, uint worker_id) { + if (!_claimed && Atomic::cmpxchg(true, &_claimed, false) == false) { + ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); + ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id); + _oops_do(cl); + } +} + +ShenandoahSerialRoots::ShenandoahSerialRoots() : + _universe_root(&Universe::oops_do, ShenandoahPhaseTimings::UniverseRoots), + _object_synchronizer_root(&ObjectSynchronizer::oops_do, ShenandoahPhaseTimings::ObjectSynchronizerRoots), + _management_root(&Management::oops_do, ShenandoahPhaseTimings::ManagementRoots), + _system_dictionary_root(&SystemDictionary::oops_do, ShenandoahPhaseTimings::SystemDictionaryRoots), + _jvmti_root(&JvmtiExport::oops_do, ShenandoahPhaseTimings::JVMTIRoots), + _jni_handle_root(&JNIHandles::oops_do, ShenandoahPhaseTimings::JNIRoots) { +} + +void ShenandoahSerialRoots::oops_do(OopClosure* cl, uint worker_id) { + _universe_root.oops_do(cl, worker_id); + _object_synchronizer_root.oops_do(cl, worker_id); + _management_root.oops_do(cl, worker_id); + _system_dictionary_root.oops_do(cl, worker_id); + _jvmti_root.oops_do(cl, worker_id); + _jni_handle_root.oops_do(cl, worker_id); +} +ShenandoahThreadRoots::ShenandoahThreadRoots(bool is_par) : _is_par(is_par) { + Threads::change_thread_claim_token(); +} + +void ShenandoahThreadRoots::oops_do(OopClosure* oops_cl, CodeBlobClosure* code_cl, uint worker_id) { + ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); + ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id); + ResourceMark rm; + Threads::possibly_parallel_oops_do(_is_par, oops_cl, code_cl); +} + +void ShenandoahThreadRoots::threads_do(ThreadClosure* tc, uint worker_id) { + ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); + ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id); + ResourceMark rm; + Threads::possibly_parallel_threads_do(_is_par, tc); +} + +ShenandoahThreadRoots::~ShenandoahThreadRoots() { + Threads::assert_all_threads_claimed(); +} + +ShenandoahWeakRoots::ShenandoahWeakRoots(uint n_workers) : + _process_timings(n_workers), + _task(&_process_timings, n_workers) { +} + +ShenandoahWeakRoots::~ShenandoahWeakRoots() { + ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); + ShenandoahTimingConverter::weak_processing_timing_to_shenandoah_timing(&_process_timings, + worker_times); +} + +ShenandoahStringDedupRoots::ShenandoahStringDedupRoots() { if (ShenandoahStringDedup::is_enabled()) { StringDedup::gc_prologue(false); } } -ShenandoahRootProcessor::~ShenandoahRootProcessor() { - delete _process_strong_tasks; +ShenandoahStringDedupRoots::~ShenandoahStringDedupRoots() { if (ShenandoahStringDedup::is_enabled()) { StringDedup::gc_epilogue(); } +} - if (_processed_weak_roots) { - assert(_weak_processor_timings.max_threads() == n_workers(), "Must match"); - ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); - ShenandoahTimingConverter::weak_processing_timing_to_shenandoah_timing(&_weak_processor_timings, - worker_times); +void ShenandoahStringDedupRoots::oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id) { + if (ShenandoahStringDedup::is_enabled()) { + ShenandoahStringDedup::parallel_oops_do(is_alive, keep_alive, worker_id); } - - ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase); } -void ShenandoahRootProcessor::process_strong_roots(OopClosure* oops, - CLDClosure* clds, - CodeBlobClosure* blobs, - ThreadClosure* thread_cl, - uint worker_id) { - - process_java_roots(oops, clds, NULL, blobs, thread_cl, worker_id); - process_vm_roots(oops, worker_id); - - _process_strong_tasks->all_tasks_completed(n_workers()); +ShenandoahClassLoaderDataRoots::ShenandoahClassLoaderDataRoots() { + ClassLoaderDataGraph::clear_claimed_marks(); } -void ShenandoahRootProcessor::process_all_roots(OopClosure* oops, - CLDClosure* clds, - CodeBlobClosure* blobs, - ThreadClosure* thread_cl, - uint worker_id) { - +void ShenandoahClassLoaderDataRoots::clds_do(CLDClosure* strong_clds, CLDClosure* weak_clds, uint worker_id) { ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); - process_java_roots(oops, clds, clds, blobs, thread_cl, worker_id); - process_vm_roots(oops, worker_id); - - if (blobs != NULL) { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id); - _coderoots_all_iterator.possibly_parallel_blobs_do(blobs); - } - - _process_strong_tasks->all_tasks_completed(n_workers()); - + ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id); + ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds); } class ShenandoahParallelOopsDoThreadClosure : public ThreadClosure { @@ -123,168 +152,110 @@ } }; -void ShenandoahRootProcessor::process_java_roots(OopClosure* strong_roots, - CLDClosure* strong_clds, - CLDClosure* weak_clds, - CodeBlobClosure* strong_code, - ThreadClosure* thread_cl, - uint worker_id) -{ - ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); - // Iterating over the CLDG and the Threads are done early to allow us to - // first process the strong CLDs and nmethods and then, after a barrier, - // let the thread process the weak CLDs and nmethods. - { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id); - _cld_iterator.root_cld_do(strong_clds, weak_clds); - } +ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase) : + _heap(ShenandoahHeap::heap()), + _phase(phase) { + assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint"); + _heap->phase_timings()->record_workers_start(_phase); +} - { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id); - bool is_par = n_workers() > 1; - ResourceMark rm; - ShenandoahParallelOopsDoThreadClosure cl(strong_roots, strong_code, thread_cl); - Threads::possibly_parallel_threads_do(is_par, &cl); - } +ShenandoahRootProcessor::~ShenandoahRootProcessor() { + assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint"); + _heap->phase_timings()->record_workers_end(_phase); +} + +ShenandoahRootScanner::ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase) : + ShenandoahRootProcessor(phase), + _thread_roots(n_workers > 1) { } -void ShenandoahRootProcessor::process_vm_roots(OopClosure* strong_roots, - uint worker_id) { - ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); - if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_Universe_oops_do)) { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::UniverseRoots, worker_id); - Universe::oops_do(strong_roots); - } +void ShenandoahRootScanner::roots_do(uint worker_id, OopClosure* oops) { + CLDToOopClosure clds_cl(oops, ClassLoaderData::_claim_strong); + MarkingCodeBlobClosure blobs_cl(oops, !CodeBlobToOopClosure::FixRelocations); + roots_do(worker_id, oops, &clds_cl, &blobs_cl); +} - if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_JNIHandles_oops_do)) { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JNIRoots, worker_id); - JNIHandles::oops_do(strong_roots); - } - if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_Management_oops_do)) { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ManagementRoots, worker_id); - Management::oops_do(strong_roots); - } - if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_jvmti_oops_do)) { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JVMTIRoots, worker_id); - JvmtiExport::oops_do(strong_roots); - } - if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_SystemDictionary_oops_do)) { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::SystemDictionaryRoots, worker_id); - SystemDictionary::oops_do(strong_roots); - } - - { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ObjectSynchronizerRoots, worker_id); - if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_ObjectSynchronizer_oops_do)) { - ObjectSynchronizer::oops_do(strong_roots); - } - } +void ShenandoahRootScanner::strong_roots_do(uint worker_id, OopClosure* oops) { + CLDToOopClosure clds_cl(oops, ClassLoaderData::_claim_strong); + MarkingCodeBlobClosure blobs_cl(oops, !CodeBlobToOopClosure::FixRelocations); + strong_roots_do(worker_id, oops, &clds_cl, &blobs_cl); } -uint ShenandoahRootProcessor::n_workers() const { - return _srs.n_threads(); -} +void ShenandoahRootScanner::roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure *tc) { + assert(!ShenandoahHeap::heap()->unload_classes(), "Should be used during class unloading"); + ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc); + ResourceMark rm; -ShenandoahRootEvacuator::ShenandoahRootEvacuator(ShenandoahHeap* heap, uint n_workers, ShenandoahPhaseTimings::Phase phase) : - _evacuation_tasks(new SubTasksDone(SHENANDOAH_EVAC_NumElements)), - _srs(n_workers), - _phase(phase), - _coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator()), - _weak_processor_timings(n_workers), - _weak_processor_task(&_weak_processor_timings, n_workers) { - heap->phase_timings()->record_workers_start(_phase); - if (ShenandoahStringDedup::is_enabled()) { - StringDedup::gc_prologue(false); + _serial_roots.oops_do(oops, worker_id); + _cld_roots.clds_do(clds, clds, worker_id); + _thread_roots.threads_do(&tc_cl, worker_id); + + // With ShenandoahConcurrentScanCodeRoots, we avoid scanning the entire code cache here, + // and instead do that in concurrent phase under the relevant lock. This saves init mark + // pause time. + if (code != NULL && !ShenandoahConcurrentScanCodeRoots) { + _code_roots.code_blobs_do(code, worker_id); } } -ShenandoahRootEvacuator::~ShenandoahRootEvacuator() { - delete _evacuation_tasks; - if (ShenandoahStringDedup::is_enabled()) { - StringDedup::gc_epilogue(); - } +void ShenandoahRootScanner::strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc) { + assert(ShenandoahHeap::heap()->unload_classes(), "Should be used during class unloading"); + ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc); + ResourceMark rm; - ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); - assert(_weak_processor_timings.max_threads() == n_workers(), "Must match"); - ShenandoahTimingConverter::weak_processing_timing_to_shenandoah_timing(&_weak_processor_timings, - worker_times); - - ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase); + _serial_roots.oops_do(oops, worker_id); + _cld_roots.clds_do(clds, NULL, worker_id); + _thread_roots.threads_do(&tc_cl, worker_id); } -void ShenandoahRootEvacuator::process_evacuate_roots(OopClosure* oops, - CodeBlobClosure* blobs, - uint worker_id) { +ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase) : + ShenandoahRootProcessor(phase), + _thread_roots(n_workers > 1), + _weak_roots(n_workers) { +} + +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; - ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); - { - bool is_par = n_workers() > 1; - ResourceMark rm; - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id); - Threads::possibly_parallel_oops_do(is_par, oops, NULL); - } - { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id); - CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong); - _cld_iterator.root_cld_do(&clds, &clds); - } + _serial_roots.oops_do(oops, worker_id); - if (blobs != NULL) { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id); - _coderoots_cset_iterator.possibly_parallel_blobs_do(blobs); - } - - if (ShenandoahStringDedup::is_enabled()) { - ShenandoahStringDedup::parallel_oops_do(&always_true, oops, worker_id); - } - - if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_Universe_oops_do)) { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::UniverseRoots, worker_id); - Universe::oops_do(oops); - } + _thread_roots.oops_do(oops, NULL, worker_id); + _cld_roots.clds_do(&clds, &clds, worker_id); + _code_roots.code_blobs_do(&blobsCl, worker_id); - if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_Management_oops_do)) { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ManagementRoots, worker_id); - Management::oops_do(oops); - } - - if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_jvmti_oops_do)) { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JVMTIRoots, worker_id); - JvmtiExport::oops_do(oops); - ShenandoahForwardedIsAliveClosure is_alive; - JvmtiExport::weak_oops_do(&is_alive, oops); - } + _weak_roots.oops_do(&always_true, oops, worker_id); + _dedup_roots.oops_do(&always_true, oops, worker_id); +} - if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_JNIHandles_oops_do)) { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JNIRoots, worker_id); - JNIHandles::oops_do(oops); - } - - if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_SystemDictionary_oops_do)) { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::SystemDictionaryRoots, worker_id); - SystemDictionary::oops_do(oops); - } - - if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_ObjectSynchronizer_oops_do)) { - ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ObjectSynchronizerRoots, worker_id); - ObjectSynchronizer::oops_do(oops); - } - - _weak_processor_task.work(worker_id, &always_true, oops); +ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool update_code_cache) : + ShenandoahRootProcessor(phase), + _thread_roots(n_workers > 1), + _weak_roots(n_workers), + _update_code_cache(update_code_cache) { } -uint ShenandoahRootEvacuator::n_workers() const { - return _srs.n_threads(); +ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) : + ShenandoahRootProcessor(phase), + _thread_roots(n_workers > 1), + _weak_roots(n_workers) { + assert(ShenandoahHeap::heap()->is_full_gc_in_progress(), "Full GC only"); } -// Implemenation of ParallelCLDRootIterator -ParallelCLDRootIterator::ParallelCLDRootIterator() { - assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint"); - ClassLoaderDataGraph::clear_claimed_marks(); +void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) { + CodeBlobToOopClosure adjust_code_closure(oops, CodeBlobToOopClosure::FixRelocations); + CLDToOopClosure adjust_cld_closure(oops, ClassLoaderData::_claim_strong); + AlwaysTrueClosure always_true; + + _serial_roots.oops_do(oops, worker_id); + + _thread_roots.oops_do(oops, NULL, worker_id); + _cld_roots.clds_do(&adjust_cld_closure, NULL, worker_id); + _code_roots.code_blobs_do(&adjust_code_closure, worker_id); + + _weak_roots.oops_do(&always_true, oops, worker_id); + _dedup_roots.oops_do(&always_true, oops, worker_id); } - -void ParallelCLDRootIterator::root_cld_do(CLDClosure* strong, CLDClosure* weak) { - ClassLoaderDataGraph::roots_cld_do(strong, weak); -} diff -r 23837d614c17 -r ba1eccda5450 src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp Fri May 17 12:33:37 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp Fri May 17 09:52:35 2019 -0400 @@ -36,110 +36,160 @@ #include "memory/allocation.hpp" #include "memory/iterator.hpp" -class ParallelCLDRootIterator { +class ShenandoahSerialRoot { +public: + typedef void (*OopsDo)(OopClosure*); +private: + volatile bool _claimed; + const OopsDo _oops_do; + const ShenandoahPhaseTimings::GCParPhases _phase; + public: - ParallelCLDRootIterator(); - void root_cld_do(CLDClosure* strong, CLDClosure* weak); + ShenandoahSerialRoot(OopsDo oops_do, ShenandoahPhaseTimings::GCParPhases); + void oops_do(OopClosure* cl, uint worker_id); +}; + +class ShenandoahSerialRoots { +private: + ShenandoahSerialRoot _universe_root; + ShenandoahSerialRoot _object_synchronizer_root; + ShenandoahSerialRoot _management_root; + ShenandoahSerialRoot _system_dictionary_root; + ShenandoahSerialRoot _jvmti_root; + ShenandoahSerialRoot _jni_handle_root; +public: + ShenandoahSerialRoots(); + void oops_do(OopClosure* cl, uint worker_id); +}; + +class ShenandoahThreadRoots { +private: + const bool _is_par; +public: + ShenandoahThreadRoots(bool is_par); + ~ShenandoahThreadRoots(); + + void oops_do(OopClosure* oops_cl, CodeBlobClosure* code_cl, uint worker_id); + void threads_do(ThreadClosure* tc, uint worker_id); }; -enum Shenandoah_process_roots_tasks { - SHENANDOAH_RP_PS_Universe_oops_do, - SHENANDOAH_RP_PS_JNIHandles_oops_do, - SHENANDOAH_RP_PS_ObjectSynchronizer_oops_do, - SHENANDOAH_RP_PS_Management_oops_do, - SHENANDOAH_RP_PS_SystemDictionary_oops_do, - SHENANDOAH_RP_PS_jvmti_oops_do, - // Leave this one last. - SHENANDOAH_RP_PS_NumElements +class ShenandoahWeakRoots { +private: + WeakProcessorPhaseTimes _process_timings; + WeakProcessor::Task _task; +public: + ShenandoahWeakRoots(uint n_workers); + ~ShenandoahWeakRoots(); + + template + void oops_do(IsAlive* is_alive, KeepAlive* keep_alive, uint worker_id); +}; + +class ShenandoahStringDedupRoots { +public: + ShenandoahStringDedupRoots(); + ~ShenandoahStringDedupRoots(); + + void oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id); +}; + +template +class ShenandoahCodeCacheRoots { +private: + ITR _coderoots_iterator; +public: + ShenandoahCodeCacheRoots(); + ~ShenandoahCodeCacheRoots(); + + void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id); +}; + +class ShenandoahClassLoaderDataRoots { +public: + ShenandoahClassLoaderDataRoots(); + + void clds_do(CLDClosure* strong_clds, CLDClosure* weak_clds, uint worker_id); }; class ShenandoahRootProcessor : public StackObj { - SubTasksDone* _process_strong_tasks; - StrongRootsScope _srs; - ShenandoahPhaseTimings::Phase _phase; - ParallelCLDRootIterator _cld_iterator; - ShenandoahAllCodeRootsIterator _coderoots_all_iterator; - CodeBlobClosure* _threads_nmethods_cl; - WeakProcessorPhaseTimes _weak_processor_timings; - WeakProcessor::Task _weak_processor_task; - bool _processed_weak_roots; - - void process_java_roots(OopClosure* scan_non_heap_roots, - CLDClosure* scan_strong_clds, - CLDClosure* scan_weak_clds, - CodeBlobClosure* scan_strong_code, - ThreadClosure* thread_cl, - uint worker_i); - - void process_vm_roots(OopClosure* scan_non_heap_roots, - uint worker_i); - - void weak_processor_timing_to_shenandoah_timing(const WeakProcessorPhases::Phase wpp, - const ShenandoahPhaseTimings::GCParPhases spp, - ShenandoahWorkerTimings* worker_times) const; - +private: + ShenandoahHeap* const _heap; + const ShenandoahPhaseTimings::Phase _phase; public: - ShenandoahRootProcessor(ShenandoahHeap* heap, uint n_workers, - ShenandoahPhaseTimings::Phase phase); + ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase); ~ShenandoahRootProcessor(); - // Apply oops, clds and blobs to all strongly reachable roots in the system. - // Optionally, apply class loader closure to weak clds, depending on class unloading - // for the particular GC cycles. - void process_strong_roots(OopClosure* oops, - CLDClosure* clds, - CodeBlobClosure* blobs, - ThreadClosure* thread_cl, - uint worker_id); + ShenandoahHeap* heap() const { return _heap; } +}; - // Apply oops, clds and blobs to strongly reachable roots in the system - void process_all_roots(OopClosure* oops, - CLDClosure* clds, - CodeBlobClosure* blobs, - ThreadClosure* thread_cl, - uint worker_id); +class ShenandoahRootScanner : public ShenandoahRootProcessor { +private: + ShenandoahSerialRoots _serial_roots; + ShenandoahClassLoaderDataRoots _cld_roots; + ShenandoahThreadRoots _thread_roots; + ShenandoahCodeCacheRoots _code_roots; +public: + ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase); - // Apply oops, clds and blobs to strongly and weakly reachable roots in the system - template - void update_all_roots(OopClosure* oops, - CLDClosure* clds, - CodeBlobClosure* blobs, - ThreadClosure* thread_cl, - uint worker_id); + // Apply oops, clds and blobs to all strongly reachable roots in the system, + // during class unloading cycle + void strong_roots_do(uint worker_id, OopClosure* cl); + void strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL); - // Number of worker threads used by the root processor. - uint n_workers() const; + // Apply oops, clds and blobs to all strongly reachable roots and weakly reachable + // roots when class unloading is disabled during this cycle + void roots_do(uint worker_id, OopClosure* cl); + void roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL); }; -class ShenandoahRootEvacuator : public StackObj { - SubTasksDone* _evacuation_tasks; - StrongRootsScope _srs; - ShenandoahPhaseTimings::Phase _phase; - ShenandoahCsetCodeRootsIterator _coderoots_cset_iterator; - ParallelCLDRootIterator _cld_iterator; - WeakProcessorPhaseTimes _weak_processor_timings; - WeakProcessor::Task _weak_processor_task; +// Evacuate all roots at a safepoint +class ShenandoahRootEvacuator : public ShenandoahRootProcessor { +private: + ShenandoahSerialRoots _serial_roots; + ShenandoahClassLoaderDataRoots _cld_roots; + ShenandoahThreadRoots _thread_roots; + ShenandoahWeakRoots _weak_roots; + ShenandoahStringDedupRoots _dedup_roots; + ShenandoahCodeCacheRoots _code_roots; + +public: + ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase); + + void roots_do(uint worker_id, OopClosure* oops); +}; - enum Shenandoah_evacuate_roots_tasks { - SHENANDOAH_EVAC_Universe_oops_do, - SHENANDOAH_EVAC_ObjectSynchronizer_oops_do, - SHENANDOAH_EVAC_Management_oops_do, - SHENANDOAH_EVAC_SystemDictionary_oops_do, - SHENANDOAH_EVAC_jvmti_oops_do, - SHENANDOAH_EVAC_JNIHandles_oops_do, - // Leave this one last. - SHENANDOAH_EVAC_NumElements - }; +// Update all roots at a safepoint +class ShenandoahRootUpdater : public ShenandoahRootProcessor { +private: + ShenandoahSerialRoots _serial_roots; + ShenandoahClassLoaderDataRoots _cld_roots; + ShenandoahThreadRoots _thread_roots; + ShenandoahWeakRoots _weak_roots; + ShenandoahStringDedupRoots _dedup_roots; + ShenandoahCodeCacheRoots _code_roots; + const bool _update_code_cache; + public: - ShenandoahRootEvacuator(ShenandoahHeap* heap, uint n_workers, - ShenandoahPhaseTimings::Phase phase); - ~ShenandoahRootEvacuator(); + ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool update_code_cache); + + template + void roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive); +}; - void process_evacuate_roots(OopClosure* oops, - CodeBlobClosure* blobs, - uint worker_id); +// Adjuster all roots at a safepoint during full gc +class ShenandoahRootAdjuster : public ShenandoahRootProcessor { +private: + ShenandoahSerialRoots _serial_roots; + ShenandoahClassLoaderDataRoots _cld_roots; + ShenandoahThreadRoots _thread_roots; + ShenandoahWeakRoots _weak_roots; + ShenandoahStringDedupRoots _dedup_roots; + ShenandoahCodeCacheRoots _code_roots; - // Number of worker threads used by the root processor. - uint n_workers() const; +public: + ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase); + + void roots_do(uint worker_id, OopClosure* oops); }; + #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP diff -r 23837d614c17 -r ba1eccda5450 src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp Fri May 17 12:33:37 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp Fri May 17 09:52:35 2019 -0400 @@ -25,22 +25,47 @@ #define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP #include "gc/shenandoah/shenandoahRootProcessor.hpp" +#include "gc/shenandoah/shenandoahTimingTracker.hpp" -template -void ShenandoahRootProcessor::update_all_roots(OopClosure* oops, - CLDClosure* clds, - CodeBlobClosure* blobs, - ThreadClosure* thread_cl, - uint worker_id) { - process_all_roots(oops, clds, blobs, thread_cl, worker_id); +template +void ShenandoahWeakRoots::oops_do(IsAlive* is_alive, KeepAlive* keep_alive, uint worker_id) { + _task.work(worker_id, is_alive, keep_alive); +} + +template +ShenandoahCodeCacheRoots::ShenandoahCodeCacheRoots() { + nmethod::oops_do_marking_prologue(); +} + +template +void ShenandoahCodeCacheRoots::code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id) { + ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); + ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id); + _coderoots_iterator.possibly_parallel_blobs_do(blob_cl); +} - IsAlive is_alive; - _weak_processor_task.work(worker_id, &is_alive, oops); - _processed_weak_roots = true; +template +ShenandoahCodeCacheRoots::~ShenandoahCodeCacheRoots() { + nmethod::oops_do_marking_epilogue(); +} + +template +void ShenandoahRootUpdater::roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive) { + CodeBlobToOopClosure update_blobs(keep_alive, CodeBlobToOopClosure::FixRelocations); + CLDToOopClosure clds(keep_alive, ClassLoaderData::_claim_strong); + CLDToOopClosure* weak_clds = ShenandoahHeap::heap()->unload_classes() ? NULL : &clds; - if (ShenandoahStringDedup::is_enabled()) { - ShenandoahStringDedup::parallel_oops_do(&is_alive, oops, worker_id); + _serial_roots.oops_do(keep_alive, worker_id); + + _thread_roots.oops_do(keep_alive, NULL, worker_id); + _cld_roots.clds_do(&clds, weak_clds, worker_id); + + if(_update_code_cache) { + _code_roots.code_blobs_do(&update_blobs, worker_id); } + + _weak_roots.oops_do(is_alive, keep_alive, worker_id); + _dedup_roots.oops_do(is_alive, keep_alive, worker_id); } #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP diff -r 23837d614c17 -r ba1eccda5450 src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp Fri May 17 12:33:37 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp Fri May 17 09:52:35 2019 -0400 @@ -161,11 +161,13 @@ class ShenandoahInitTraversalCollectionTask : public AbstractGangTask { private: - ShenandoahRootProcessor* _rp; + ShenandoahRootScanner* _rp; ShenandoahHeap* _heap; ShenandoahCsetCodeRootsIterator* _cset_coderoots; + ShenandoahStringDedupRoots _dedup_roots; + public: - ShenandoahInitTraversalCollectionTask(ShenandoahRootProcessor* rp, ShenandoahCsetCodeRootsIterator* cset_coderoots) : + ShenandoahInitTraversalCollectionTask(ShenandoahRootScanner* rp, ShenandoahCsetCodeRootsIterator* cset_coderoots) : AbstractGangTask("Shenandoah Init Traversal Collection"), _rp(rp), _heap(ShenandoahHeap::heap()), @@ -191,18 +193,17 @@ ShenandoahMarkCLDClosure cld_cl(&roots_cl); MarkingCodeBlobClosure code_cl(&roots_cl, CodeBlobToOopClosure::FixRelocations); if (unload_classes) { - _rp->process_strong_roots(&roots_cl, &cld_cl, NULL, NULL, worker_id); + _rp->strong_roots_do(worker_id, &roots_cl); // Need to pre-evac code roots here. Otherwise we might see from-space constants. ShenandoahWorkerTimings* worker_times = _heap->phase_timings()->worker_times(); ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id); _cset_coderoots->possibly_parallel_blobs_do(&code_cl); } else { - _rp->process_all_roots(&roots_cl, &cld_cl, &code_cl, NULL, worker_id); + _rp->roots_do(worker_id, &roots_cl, &cld_cl, &code_cl); } - if (ShenandoahStringDedup::is_enabled()) { - AlwaysTrueClosure is_alive; - ShenandoahStringDedup::parallel_oops_do(&is_alive, &roots_cl, worker_id); - } + + AlwaysTrueClosure is_alive; + _dedup_roots.oops_do(&is_alive, &roots_cl, worker_id); } } }; @@ -230,11 +231,11 @@ class ShenandoahFinalTraversalCollectionTask : public AbstractGangTask { private: - ShenandoahRootProcessor* _rp; + ShenandoahRootScanner* _rp; ShenandoahTaskTerminator* _terminator; ShenandoahHeap* _heap; public: - ShenandoahFinalTraversalCollectionTask(ShenandoahRootProcessor* rp, ShenandoahTaskTerminator* terminator) : + ShenandoahFinalTraversalCollectionTask(ShenandoahRootScanner* rp, ShenandoahTaskTerminator* terminator) : AbstractGangTask("Shenandoah Final Traversal Collection"), _rp(rp), _terminator(terminator), @@ -273,23 +274,23 @@ // roots here. if (!_heap->is_degenerated_gc_in_progress()) { ShenandoahTraversalClosure roots_cl(q, rp); - CLDToOopClosure cld_cl(&roots_cl, ClassLoaderData::_claim_strong); ShenandoahTraversalSATBThreadsClosure tc(&satb_cl); if (unload_classes) { ShenandoahRemarkCLDClosure remark_cld_cl(&roots_cl); - _rp->process_strong_roots(&roots_cl, &remark_cld_cl, NULL, &tc, worker_id); + _rp->strong_roots_do(worker_id, &roots_cl, &remark_cld_cl, NULL, &tc); } else { - _rp->process_all_roots(&roots_cl, &cld_cl, NULL, &tc, worker_id); + CLDToOopClosure cld_cl(&roots_cl, ClassLoaderData::_claim_strong); + _rp->roots_do(worker_id, &roots_cl, &cld_cl, NULL, &tc); } } else { ShenandoahTraversalDegenClosure roots_cl(q, rp); - CLDToOopClosure cld_cl(&roots_cl, ClassLoaderData::_claim_strong); ShenandoahTraversalSATBThreadsClosure tc(&satb_cl); if (unload_classes) { ShenandoahRemarkCLDClosure remark_cld_cl(&roots_cl); - _rp->process_strong_roots(&roots_cl, &remark_cld_cl, NULL, &tc, worker_id); + _rp->strong_roots_do(worker_id, &roots_cl, &remark_cld_cl, NULL, &tc); } else { - _rp->process_all_roots(&roots_cl, &cld_cl, NULL, &tc, worker_id); + CLDToOopClosure cld_cl(&roots_cl, ClassLoaderData::_claim_strong); + _rp->roots_do(worker_id, &roots_cl, &cld_cl, NULL, &tc); } } @@ -309,6 +310,9 @@ _task_queues(new ShenandoahObjToScanQueueSet(heap->max_workers())), _traversal_set(ShenandoahHeapRegionSet()) { + // Traversal does not support concurrent code root scanning + FLAG_SET_DEFAULT(ShenandoahConcurrentScanCodeRoots, false); + uint num_queues = heap->max_workers(); for (uint i = 0; i < num_queues; ++i) { ShenandoahObjToScanQueue* task_queue = new ShenandoahObjToScanQueue(); @@ -411,7 +415,7 @@ { uint nworkers = _heap->workers()->active_workers(); task_queues()->reserve(nworkers); - ShenandoahRootProcessor rp(_heap, nworkers, ShenandoahPhaseTimings::init_traversal_gc_work); + ShenandoahRootScanner rp(nworkers, ShenandoahPhaseTimings::init_traversal_gc_work); ShenandoahCsetCodeRootsIterator cset_coderoots = ShenandoahCodeRoots::cset_iterator(); @@ -584,7 +588,7 @@ task_queues()->reserve(nworkers); // Finish traversal - ShenandoahRootProcessor rp(_heap, nworkers, ShenandoahPhaseTimings::final_traversal_gc_work); + ShenandoahRootScanner rp(nworkers, ShenandoahPhaseTimings::final_traversal_gc_work); ShenandoahTerminationTracker term(ShenandoahPhaseTimings::final_traversal_gc_termination); ShenandoahTaskTerminator terminator(nworkers, task_queues()); @@ -693,10 +697,10 @@ class ShenandoahTraversalFixRootsTask : public AbstractGangTask { private: - ShenandoahRootProcessor* _rp; + ShenandoahRootUpdater* _rp; public: - ShenandoahTraversalFixRootsTask(ShenandoahRootProcessor* rp) : + ShenandoahTraversalFixRootsTask(ShenandoahRootUpdater* rp) : AbstractGangTask("Shenandoah traversal fix roots"), _rp(rp) { assert(ShenandoahHeap::heap()->has_forwarded_objects(), "Must be"); @@ -705,9 +709,8 @@ void work(uint worker_id) { ShenandoahParallelWorkerSession worker_session(worker_id); ShenandoahTraversalFixRootsClosure cl; - MarkingCodeBlobClosure blobsCl(&cl, CodeBlobToOopClosure::FixRelocations); - CLDToOopClosure cldCl(&cl, ClassLoaderData::_claim_strong); - _rp->update_all_roots(&cl, &cldCl, &blobsCl, NULL, worker_id); + ShenandoahForwardedIsAliveClosure is_alive; + _rp->roots_do(worker_id, &is_alive, &cl); } }; @@ -715,7 +718,7 @@ #if defined(COMPILER2) || INCLUDE_JVMCI DerivedPointerTable::clear(); #endif - ShenandoahRootProcessor rp(_heap, _heap->workers()->active_workers(), ShenandoahPhaseTimings::final_traversal_update_roots); + ShenandoahRootUpdater rp(_heap->workers()->active_workers(), ShenandoahPhaseTimings::final_traversal_update_roots, true /* update code cache */); ShenandoahTraversalFixRootsTask update_roots_task(&rp); _heap->workers()->run_task(&update_roots_task); #if defined(COMPILER2) || INCLUDE_JVMCI