< prev index next >

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

Print this page

        

*** 25,200 **** #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" #include "gc/shared/weakProcessor.inline.hpp" #include "memory/allocation.inline.hpp" #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" - #include "memory/universe.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); } ! ShenandoahStringDedupRoots::ShenandoahStringDedupRoots() { if (ShenandoahStringDedup::is_enabled()) { StringDedup::gc_prologue(false); } } ! ShenandoahStringDedupRoots::~ShenandoahStringDedupRoots() { if (ShenandoahStringDedup::is_enabled()) { StringDedup::gc_epilogue(); } } ! 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); ! } ! } ! ! ShenandoahClassLoaderDataRoots::ShenandoahClassLoaderDataRoots() { ! ClassLoaderDataGraph::clear_claimed_marks(); ! } - void ShenandoahClassLoaderDataRoots::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); ! } ! 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); ! } ! ShenandoahRootProcessor::~ShenandoahRootProcessor() { ! assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint"); ! _heap->phase_timings()->record_workers_end(_phase); ! } ! 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; ! _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); } ! 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) { } ! 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"); } ! 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); } --- 25,327 ---- #include "classfile/classLoaderDataGraph.hpp" #include "classfile/stringTable.hpp" #include "classfile/systemDictionary.hpp" #include "code/codeCache.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" #include "gc/shared/weakProcessor.inline.hpp" #include "memory/allocation.inline.hpp" #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "runtime/thread.hpp" #include "services/management.hpp" ! struct PhaseMap { ! WeakProcessorPhases::Phase _weak_processor_phase; ! ShenandoahPhaseTimings::GCParPhases _shenandoah_phase; ! }; ! ! static const struct PhaseMap phase_mapping[] = { ! #if INCLUDE_JVMTI ! {WeakProcessorPhases::jvmti, ShenandoahPhaseTimings::JVMTIWeakRoots}, ! #endif ! #if INCLUDE_JFR ! {WeakProcessorPhases::jfr, ShenandoahPhaseTimings::JFRWeakRoots}, ! #endif ! {WeakProcessorPhases::jni, ShenandoahPhaseTimings::JNIWeakRoots}, ! {WeakProcessorPhases::stringtable, ShenandoahPhaseTimings::StringTableRoots}, ! {WeakProcessorPhases::vm, ShenandoahPhaseTimings::VMWeakRoots} ! }; ! ! STATIC_ASSERT(sizeof(phase_mapping) / sizeof(PhaseMap) == WeakProcessorPhases::phase_count); ! ! ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahHeap* heap, uint n_workers, ! ShenandoahPhaseTimings::Phase phase) : ! _process_strong_tasks(new SubTasksDone(SHENANDOAH_RP_PS_NumElements)), ! _srs(n_workers), ! _par_state_string(StringTable::weak_storage()), ! _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(); ! } ! ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); ! ! if (_processed_weak_roots) { ! assert(_weak_processor_timings.max_threads() == n_workers(), "Must match"); ! for (uint index = 0; index < WeakProcessorPhases::phase_count; index ++) { ! weak_processor_timing_to_shenandoah_timing(phase_mapping[index]._weak_processor_phase, ! phase_mapping[index]._shenandoah_phase, ! worker_times); ! } ! } ! ! ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase); } ! void ShenandoahRootProcessor::weak_processor_timing_to_shenandoah_timing(const WeakProcessorPhases::Phase wpp, ! const ShenandoahPhaseTimings::GCParPhases spp, ! ShenandoahWorkerTimings* worker_times) const { ! if (WeakProcessorPhases::is_serial(wpp)) { ! worker_times->record_time_secs(spp, 0, _weak_processor_timings.phase_time_sec(wpp)); ! } else { ! for (uint index = 0; index < _weak_processor_timings.max_threads(); index ++) { ! worker_times->record_time_secs(spp, index, _weak_processor_timings.worker_time_sec(index, wpp)); ! } ! } } ! void ShenandoahRootProcessor::process_all_roots_slow(OopClosure* oops) { ! CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong); ! CodeBlobToOopClosure blobs(oops, !CodeBlobToOopClosure::FixRelocations); ! ! CodeCache::blobs_do(&blobs); ! ClassLoaderDataGraph::cld_do(&clds); ! Universe::oops_do(oops); ! Management::oops_do(oops); ! JvmtiExport::oops_do(oops); ! JNIHandles::oops_do(oops); ! ObjectSynchronizer::oops_do(oops); ! SystemDictionary::oops_do(oops); ! ! // Do thread roots the last. This allows verification code to find ! // any broken objects from those special roots first, not the accidental ! // dangling reference from the thread root. ! Threads::possibly_parallel_oops_do(false, oops, &blobs); ! } ! ! 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; ! CodeBlobClosure* _cf; ! ThreadClosure* _thread_cl; ! public: ! ShenandoahParallelOopsDoThreadClosure(OopClosure* f, CodeBlobClosure* cf, ThreadClosure* thread_cl) : ! _f(f), _cf(cf), _thread_cl(thread_cl) {} ! ! void do_thread(Thread* t) { ! if (_thread_cl != NULL) { ! _thread_cl->do_thread(t); ! } ! 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()), ! _par_state_string(StringTable::weak_storage()) ! ! { ! 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(); } + ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase); } ! void ShenandoahRootEvacuator::process_evacuate_roots(OopClosure* oops, ! CodeBlobClosure* blobs, ! uint worker_id) { 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); ! } ! if (blobs != NULL) { ! ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id); ! _coderoots_cset_iterator.possibly_parallel_blobs_do(blobs); ! } ! if (ShenandoahStringDedup::is_enabled()) { ! ShenandoahForwardedIsAliveClosure is_alive; ! ShenandoahStringDedup::parallel_oops_do(&is_alive, 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_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); ! } } ! 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); }
< prev index next >