< prev index next >

src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp

Print this page
rev 54809 : 8223215: Shenandoah: Support verifying subset of roots
rev 54810 : 8223774: Shenandoah: Refactor ShenandoahRootProcessor and family

*** 26,37 **** #include "classfile/classLoaderDataGraph.hpp" #include "classfile/stringTable.hpp" #include "classfile/systemDictionary.hpp" #include "code/codeCache.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" ! #include "gc/shenandoah/shenandoahRootProcessor.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahStringDedup.hpp" #include "gc/shenandoah/shenandoahTimingTracker.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahVMOperations.hpp" --- 26,38 ---- #include "classfile/classLoaderDataGraph.hpp" #include "classfile/stringTable.hpp" #include "classfile/systemDictionary.hpp" #include "code/codeCache.hpp" #include "gc/shenandoah/shenandoahClosures.inline.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" #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahVMOperations.hpp"
*** 40,110 **** #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #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); ! if (ShenandoahStringDedup::is_enabled()) { ! StringDedup::gc_prologue(false); } } ! ShenandoahRootProcessor::~ShenandoahRootProcessor() { ! delete _process_strong_tasks; ! 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); ! } ! 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()); ! } ! ! void ShenandoahRootProcessor::process_all_roots(OopClosure* oops, ! CLDClosure* clds, ! CodeBlobClosure* blobs, ! ThreadClosure* thread_cl, ! 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()); } class ShenandoahParallelOopsDoThreadClosure : public ThreadClosure { private: OopClosure* _f; --- 41,139 ---- #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "runtime/thread.hpp" #include "services/management.hpp" ! 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); ! } ! ShenandoahStringDedupRoot::ShenandoahStringDedupRoot() { ! if (ShenandoahStringDedup::is_enabled()) { ! StringDedup::gc_prologue(false); ! } ! } ! ! ShenandoahStringDedupRoot::~ShenandoahStringDedupRoot() { ! if (ShenandoahStringDedup::is_enabled()) { ! StringDedup::gc_epilogue(); } + } ! void ShenandoahStringDedupRoot::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); ! } ! } ! ! ShenandoahClassLoaderDataRoot::ShenandoahClassLoaderDataRoot() { ! ClassLoaderDataGraph::clear_claimed_marks(); ! } + void ShenandoahClassLoaderDataRoot::clds_do(CLDClosure* strong_clds, CLDClosure* weak_clds, uint worker_id) { + ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); + ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id); + ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds); } class ShenandoahParallelOopsDoThreadClosure : public ThreadClosure { private: OopClosure* _f;
*** 120,289 **** } t->oops_do(_f, _cf); } }; ! 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); ! } ! ! { ! 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); ! } } ! 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); ! } ! ! 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); ! } ! } } ! uint ShenandoahRootProcessor::n_workers() const { ! return _srs.n_threads(); } ! 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); } } ! ShenandoahRootEvacuator::~ShenandoahRootEvacuator() { ! delete _evacuation_tasks; ! if (ShenandoahStringDedup::is_enabled()) { ! StringDedup::gc_epilogue(); ! } ! 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); } ! void ShenandoahRootEvacuator::process_evacuate_roots(OopClosure* oops, ! CodeBlobClosure* blobs, ! uint worker_id) { 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); ! } ! 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); ! } ! 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); ! } - 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<AlwaysTrueClosure, OopClosure>(worker_id, &always_true, oops); ! } ! uint ShenandoahRootEvacuator::n_workers() const { ! return _srs.n_threads(); ! } ! // Implemenation of ParallelCLDRootIterator ! ParallelCLDRootIterator::ParallelCLDRootIterator() { ! assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint"); ! ClassLoaderDataGraph::clear_claimed_marks(); } ! void ParallelCLDRootIterator::root_cld_do(CLDClosure* strong, CLDClosure* weak) { ! ClassLoaderDataGraph::roots_cld_do(strong, weak); } --- 149,270 ---- } t->oops_do(_f, _cf); } }; ! ShenandoahRootProcessor::ShenandoahRootProcessor(uint n_workers, ShenandoahPhaseTimings::Phase phase) : ! _thread_roots(n_workers > 1), ! _phase(phase) { ! assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint"); ! ShenandoahHeap::heap()->phase_timings()->record_workers_start(_phase); } ! ShenandoahRootProcessor::~ShenandoahRootProcessor() { ! ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase); ! } ! void ShenandoahRootProcessor::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); } ! void ShenandoahRootProcessor::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); } ! void ShenandoahRootProcessor::roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure *tc) { ! assert(!ShenandoahHeap::heap()->unload_classes(), "Use without class unloading"); ! ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc); ! ResourceMark rm; ! ! _serial_roots.oops_do(oops, worker_id); ! _cld_roots.clds_do(clds, clds, worker_id); ! _thread_roots.threads_do(&tc_cl, worker_id); ! ! if (code != NULL && !ShenandoahConcurrentScanCodeRoots) { ! _code_roots.code_blobs_do(code, worker_id); } } ! void ShenandoahRootProcessor::strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc) { ! assert(ShenandoahHeap::heap()->unload_classes(), "Use with class unloading cycle"); ! ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc); ! ResourceMark rm; ! _serial_roots.oops_do(oops, worker_id); ! _cld_roots.clds_do(clds, NULL, worker_id); ! _thread_roots.threads_do(&tc_cl, worker_id); ! } ! ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase) : ! _thread_roots(n_workers > 1), ! _weak_roots(n_workers), ! _phase(phase) { ! assert(SafepointSynchronize::is_at_safepoint(), "Must at a safepoint"); ! ShenandoahHeap::heap()->phase_timings()->record_workers_start(_phase); } ! 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); ! _thread_roots.oops_do(oops, NULL, worker_id); ! _cld_roots.clds_do(&clds, &clds, worker_id); ! _code_roots.code_blobs_do(&blobsCl, worker_id); ! _weak_roots.oops_do<AlwaysTrueClosure, OopClosure>(&always_true, oops, worker_id); ! _dedup_roots.oops_do(&always_true, oops, worker_id); ! } ! ShenandoahRootEvacuator::~ShenandoahRootEvacuator() { ! ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase); ! } ! ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool update_code_cache) : ! _thread_roots(n_workers > 1), ! _weak_roots(n_workers), ! _phase(phase), ! _update_code_cache(update_code_cache) { ! assert(SafepointSynchronize::is_at_safepoint(), "Must at a safepoint"); ! ShenandoahHeap::heap()->phase_timings()->record_workers_start(_phase); ! } ! ShenandoahRootUpdater::~ShenandoahRootUpdater() { ! ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase); ! } ! ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) : ! _thread_roots(n_workers > 1), ! _weak_roots(n_workers), ! _phase(phase) { ! assert(SafepointSynchronize::is_at_safepoint(), "Must at a safepoint"); ! assert(ShenandoahHeap::heap()->is_full_gc_in_progress(), "Full GC only"); ! ShenandoahHeap::heap()->phase_timings()->record_workers_start(_phase); ! } ! 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<AlwaysTrueClosure, OopClosure>(&always_true, oops, worker_id); ! _dedup_roots.oops_do(&always_true, oops, worker_id); } ! ShenandoahRootAdjuster::~ShenandoahRootAdjuster() { ! ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase); }
< prev index next >