< 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 >