mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 02:54:35 +02:00
8223774: Shenandoah: Refactor ShenandoahRootProcessor and family
Reviewed-by: shade, rkennke
This commit is contained in:
parent
0a6207fe69
commit
3ebc657e40
7 changed files with 387 additions and 384 deletions
|
@ -81,10 +81,10 @@ ShenandoahMarkRefsSuperClosure::ShenandoahMarkRefsSuperClosure(ShenandoahObjToSc
|
||||||
template<UpdateRefsMode UPDATE_REFS>
|
template<UpdateRefsMode UPDATE_REFS>
|
||||||
class ShenandoahInitMarkRootsTask : public AbstractGangTask {
|
class ShenandoahInitMarkRootsTask : public AbstractGangTask {
|
||||||
private:
|
private:
|
||||||
ShenandoahRootProcessor* _rp;
|
ShenandoahRootScanner* _rp;
|
||||||
bool _process_refs;
|
bool _process_refs;
|
||||||
public:
|
public:
|
||||||
ShenandoahInitMarkRootsTask(ShenandoahRootProcessor* rp, bool process_refs) :
|
ShenandoahInitMarkRootsTask(ShenandoahRootScanner* rp, bool process_refs) :
|
||||||
AbstractGangTask("Shenandoah init mark roots task"),
|
AbstractGangTask("Shenandoah init mark roots task"),
|
||||||
_rp(rp),
|
_rp(rp),
|
||||||
_process_refs(process_refs) {
|
_process_refs(process_refs) {
|
||||||
|
@ -115,45 +115,21 @@ private:
|
||||||
// cache, because there could be the case of embedded class/oop in the generated code,
|
// 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),
|
// which we will never visit during mark. Without code cache invalidation, as in (a),
|
||||||
// we risk executing that code cache blob, and crashing.
|
// 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()) {
|
if (heap->unload_classes()) {
|
||||||
_rp->process_strong_roots(oops, &clds_cl, &blobs_cl, NULL, worker_id);
|
_rp->strong_roots_do(worker_id, oops);
|
||||||
} else {
|
} else {
|
||||||
if (ShenandoahConcurrentScanCodeRoots) {
|
_rp->roots_do(worker_id, oops);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ShenandoahUpdateRootsTask : public AbstractGangTask {
|
class ShenandoahUpdateRootsTask : public AbstractGangTask {
|
||||||
private:
|
private:
|
||||||
ShenandoahRootProcessor* _rp;
|
ShenandoahRootUpdater* _root_updater;
|
||||||
const bool _update_code_cache;
|
|
||||||
public:
|
public:
|
||||||
ShenandoahUpdateRootsTask(ShenandoahRootProcessor* rp, bool update_code_cache) :
|
ShenandoahUpdateRootsTask(ShenandoahRootUpdater* root_updater) :
|
||||||
AbstractGangTask("Shenandoah update roots task"),
|
AbstractGangTask("Shenandoah update roots task"),
|
||||||
_rp(rp),
|
_root_updater(root_updater) {
|
||||||
_update_code_cache(update_code_cache) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void work(uint worker_id) {
|
void work(uint worker_id) {
|
||||||
|
@ -162,22 +138,8 @@ public:
|
||||||
|
|
||||||
ShenandoahHeap* heap = ShenandoahHeap::heap();
|
ShenandoahHeap* heap = ShenandoahHeap::heap();
|
||||||
ShenandoahUpdateRefsClosure cl;
|
ShenandoahUpdateRefsClosure cl;
|
||||||
CLDToOopClosure cldCl(&cl, ClassLoaderData::_claim_strong);
|
AlwaysTrueClosure always_true;
|
||||||
|
_root_updater->roots_do<AlwaysTrueClosure, ShenandoahUpdateRefsClosure>(worker_id, &always_true, &cl);
|
||||||
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<AlwaysTrueClosure>(&cl, &cldCl, code_blobs, NULL, worker_id);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -289,7 +251,7 @@ void ShenandoahConcurrentMark::mark_roots(ShenandoahPhaseTimings::Phase root_pha
|
||||||
|
|
||||||
assert(nworkers <= task_queues()->size(), "Just check");
|
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());
|
TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
|
||||||
task_queues()->reserve(nworkers);
|
task_queues()->reserve(nworkers);
|
||||||
|
|
||||||
|
@ -333,8 +295,8 @@ void ShenandoahConcurrentMark::update_roots(ShenandoahPhaseTimings::Phase root_p
|
||||||
|
|
||||||
uint nworkers = _heap->workers()->active_workers();
|
uint nworkers = _heap->workers()->active_workers();
|
||||||
|
|
||||||
ShenandoahRootProcessor root_proc(_heap, nworkers, root_phase);
|
ShenandoahRootUpdater root_updater(nworkers, root_phase, update_code_cache);
|
||||||
ShenandoahUpdateRootsTask update_roots(&root_proc, update_code_cache);
|
ShenandoahUpdateRootsTask update_roots(&root_updater);
|
||||||
_heap->workers()->run_task(&update_roots);
|
_heap->workers()->run_task(&update_roots);
|
||||||
|
|
||||||
#if defined(COMPILER2) || INCLUDE_JVMCI
|
#if defined(COMPILER2) || INCLUDE_JVMCI
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
#include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
|
#include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
|
||||||
#include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
|
#include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
|
||||||
#include "gc/shenandoah/shenandoahPacer.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/shenandoahStringDedup.hpp"
|
||||||
#include "gc/shenandoah/shenandoahTaskqueue.hpp"
|
#include "gc/shenandoah/shenandoahTaskqueue.hpp"
|
||||||
#include "gc/shenandoah/shenandoahUtils.hpp"
|
#include "gc/shenandoah/shenandoahUtils.hpp"
|
||||||
|
@ -1111,7 +1111,7 @@ public:
|
||||||
ShenandoahEvacOOMScope oom_evac_scope;
|
ShenandoahEvacOOMScope oom_evac_scope;
|
||||||
ShenandoahEvacuateUpdateRootsClosure cl;
|
ShenandoahEvacuateUpdateRootsClosure cl;
|
||||||
MarkingCodeBlobClosure blobsCl(&cl, CodeBlobToOopClosure::FixRelocations);
|
MarkingCodeBlobClosure blobsCl(&cl, CodeBlobToOopClosure::FixRelocations);
|
||||||
_rp->process_evacuate_roots(&cl, &blobsCl, worker_id);
|
_rp->roots_do(worker_id, &cl);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1122,7 +1122,7 @@ void ShenandoahHeap::evacuate_and_update_roots() {
|
||||||
assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Only iterate roots while world is stopped");
|
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);
|
ShenandoahEvacuateUpdateRootsTask roots_task(&rp);
|
||||||
workers()->run_task(&roots_task);
|
workers()->run_task(&roots_task);
|
||||||
}
|
}
|
||||||
|
@ -1326,11 +1326,9 @@ void ShenandoahHeap::object_iterate(ObjectClosure* cl) {
|
||||||
Stack<oop,mtGC> oop_stack;
|
Stack<oop,mtGC> oop_stack;
|
||||||
|
|
||||||
// First, we process all GC roots. This populates the work stack with initial objects.
|
// 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);
|
ObjectIterateScanRootClosure oops(&_aux_bit_map, &oop_stack);
|
||||||
CLDToOopClosure clds(&oops, ClassLoaderData::_claim_none);
|
rp.roots_do(0, &oops);
|
||||||
CodeBlobToOopClosure blobs(&oops, false);
|
|
||||||
rp.process_all_roots(&oops, &clds, &blobs, NULL, 0);
|
|
||||||
|
|
||||||
// Work through the oop stack to traverse heap.
|
// Work through the oop stack to traverse heap.
|
||||||
while (! oop_stack.is_empty()) {
|
while (! oop_stack.is_empty()) {
|
||||||
|
|
|
@ -561,22 +561,16 @@ public:
|
||||||
|
|
||||||
class ShenandoahAdjustRootPointersTask : public AbstractGangTask {
|
class ShenandoahAdjustRootPointersTask : public AbstractGangTask {
|
||||||
private:
|
private:
|
||||||
ShenandoahRootProcessor* _rp;
|
ShenandoahRootAdjuster* _rp;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ShenandoahAdjustRootPointersTask(ShenandoahRootProcessor* rp) :
|
ShenandoahAdjustRootPointersTask(ShenandoahRootAdjuster* rp) :
|
||||||
AbstractGangTask("Shenandoah Adjust Root Pointers Task"),
|
AbstractGangTask("Shenandoah Adjust Root Pointers Task"),
|
||||||
_rp(rp) {}
|
_rp(rp) {}
|
||||||
|
|
||||||
void work(uint worker_id) {
|
void work(uint worker_id) {
|
||||||
ShenandoahAdjustPointersClosure cl;
|
ShenandoahAdjustPointersClosure cl;
|
||||||
CLDToOopClosure adjust_cld_closure(&cl, ClassLoaderData::_claim_strong);
|
_rp->roots_do(worker_id, &cl);
|
||||||
MarkingCodeBlobClosure adjust_code_closure(&cl,
|
|
||||||
CodeBlobToOopClosure::FixRelocations);
|
|
||||||
|
|
||||||
_rp->update_all_roots<AlwaysTrueClosure>(&cl,
|
|
||||||
&adjust_cld_closure,
|
|
||||||
&adjust_code_closure, NULL, worker_id);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -592,7 +586,7 @@ void ShenandoahMarkCompact::phase3_update_references() {
|
||||||
#if COMPILER2_OR_JVMCI
|
#if COMPILER2_OR_JVMCI
|
||||||
DerivedPointerTable::clear();
|
DerivedPointerTable::clear();
|
||||||
#endif
|
#endif
|
||||||
ShenandoahRootProcessor rp(heap, nworkers, ShenandoahPhaseTimings::full_gc_roots);
|
ShenandoahRootAdjuster rp(nworkers, ShenandoahPhaseTimings::full_gc_roots);
|
||||||
ShenandoahAdjustRootPointersTask task(&rp);
|
ShenandoahAdjustRootPointersTask task(&rp);
|
||||||
workers->run_task(&task);
|
workers->run_task(&task);
|
||||||
#if COMPILER2_OR_JVMCI
|
#if COMPILER2_OR_JVMCI
|
||||||
|
|
|
@ -28,8 +28,9 @@
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "gc/shenandoah/shenandoahClosures.inline.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/shenandoahHeap.hpp"
|
||||||
|
#include "gc/shenandoah/shenandoahHeuristics.hpp"
|
||||||
#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
|
#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
|
||||||
#include "gc/shenandoah/shenandoahStringDedup.hpp"
|
#include "gc/shenandoah/shenandoahStringDedup.hpp"
|
||||||
#include "gc/shenandoah/shenandoahTimingTracker.hpp"
|
#include "gc/shenandoah/shenandoahTimingTracker.hpp"
|
||||||
|
@ -43,67 +44,95 @@
|
||||||
#include "runtime/thread.hpp"
|
#include "runtime/thread.hpp"
|
||||||
#include "services/management.hpp"
|
#include "services/management.hpp"
|
||||||
|
|
||||||
ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahHeap* heap, uint n_workers,
|
ShenandoahSerialRoot::ShenandoahSerialRoot(ShenandoahSerialRoot::OopsDo oops_do, ShenandoahPhaseTimings::GCParPhases phase) :
|
||||||
ShenandoahPhaseTimings::Phase phase) :
|
_claimed(false), _oops_do(oops_do), _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);
|
|
||||||
|
|
||||||
|
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()) {
|
if (ShenandoahStringDedup::is_enabled()) {
|
||||||
StringDedup::gc_prologue(false);
|
StringDedup::gc_prologue(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShenandoahRootProcessor::~ShenandoahRootProcessor() {
|
ShenandoahStringDedupRoots::~ShenandoahStringDedupRoots() {
|
||||||
delete _process_strong_tasks;
|
|
||||||
if (ShenandoahStringDedup::is_enabled()) {
|
if (ShenandoahStringDedup::is_enabled()) {
|
||||||
StringDedup::gc_epilogue();
|
StringDedup::gc_epilogue();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_processed_weak_roots) {
|
void ShenandoahStringDedupRoots::oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id) {
|
||||||
assert(_weak_processor_timings.max_threads() == n_workers(), "Must match");
|
if (ShenandoahStringDedup::is_enabled()) {
|
||||||
ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
|
ShenandoahStringDedup::parallel_oops_do(is_alive, keep_alive, worker_id);
|
||||||
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,
|
ShenandoahClassLoaderDataRoots::ShenandoahClassLoaderDataRoots() {
|
||||||
CLDClosure* clds,
|
ClassLoaderDataGraph::clear_claimed_marks();
|
||||||
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,
|
void ShenandoahClassLoaderDataRoots::clds_do(CLDClosure* strong_clds, CLDClosure* weak_clds, uint worker_id) {
|
||||||
CLDClosure* clds,
|
|
||||||
CodeBlobClosure* blobs,
|
|
||||||
ThreadClosure* thread_cl,
|
|
||||||
uint worker_id) {
|
|
||||||
|
|
||||||
ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
|
ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
|
||||||
process_java_roots(oops, clds, clds, blobs, thread_cl, worker_id);
|
ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id);
|
||||||
process_vm_roots(oops, worker_id);
|
ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds);
|
||||||
|
|
||||||
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 {
|
class ShenandoahParallelOopsDoThreadClosure : public ThreadClosure {
|
||||||
|
@ -123,168 +152,110 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void ShenandoahRootProcessor::process_java_roots(OopClosure* strong_roots,
|
ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase) :
|
||||||
CLDClosure* strong_clds,
|
_heap(ShenandoahHeap::heap()),
|
||||||
CLDClosure* weak_clds,
|
_phase(phase) {
|
||||||
CodeBlobClosure* strong_code,
|
assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint");
|
||||||
ThreadClosure* thread_cl,
|
_heap->phase_timings()->record_workers_start(_phase);
|
||||||
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() {
|
||||||
ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id);
|
assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint");
|
||||||
bool is_par = n_workers() > 1;
|
_heap->phase_timings()->record_workers_end(_phase);
|
||||||
ResourceMark rm;
|
}
|
||||||
ShenandoahParallelOopsDoThreadClosure cl(strong_roots, strong_code, thread_cl);
|
|
||||||
Threads::possibly_parallel_threads_do(is_par, &cl);
|
ShenandoahRootScanner::ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
|
||||||
|
ShenandoahRootProcessor(phase),
|
||||||
|
_thread_roots(n_workers > 1) {
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
_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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShenandoahRootProcessor::process_vm_roots(OopClosure* strong_roots,
|
void ShenandoahRootScanner::strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc) {
|
||||||
uint worker_id) {
|
assert(ShenandoahHeap::heap()->unload_classes(), "Should be used during class unloading");
|
||||||
ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
|
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc);
|
||||||
if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_Universe_oops_do)) {
|
ResourceMark rm;
|
||||||
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)) {
|
_serial_roots.oops_do(oops, worker_id);
|
||||||
ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JNIRoots, worker_id);
|
_cld_roots.clds_do(clds, NULL, worker_id);
|
||||||
JNIHandles::oops_do(strong_roots);
|
_thread_roots.threads_do(&tc_cl, worker_id);
|
||||||
}
|
|
||||||
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 {
|
ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
|
||||||
return _srs.n_threads();
|
ShenandoahRootProcessor(phase),
|
||||||
|
_thread_roots(n_workers > 1),
|
||||||
|
_weak_roots(n_workers) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ShenandoahRootEvacuator::ShenandoahRootEvacuator(ShenandoahHeap* heap, uint n_workers, ShenandoahPhaseTimings::Phase phase) :
|
void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) {
|
||||||
_evacuation_tasks(new SubTasksDone(SHENANDOAH_EVAC_NumElements)),
|
MarkingCodeBlobClosure blobsCl(oops, CodeBlobToOopClosure::FixRelocations);
|
||||||
_srs(n_workers),
|
CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong);
|
||||||
_phase(phase),
|
CLDToOopClosure* weak_clds = ShenandoahHeap::heap()->unload_classes() ? NULL : &clds;
|
||||||
_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;
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
_serial_roots.oops_do(oops, worker_id);
|
||||||
ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id);
|
|
||||||
CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong);
|
|
||||||
_cld_iterator.root_cld_do(&clds, &clds);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blobs != NULL) {
|
_thread_roots.oops_do(oops, NULL, worker_id);
|
||||||
ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id);
|
_cld_roots.clds_do(&clds, &clds, worker_id);
|
||||||
_coderoots_cset_iterator.possibly_parallel_blobs_do(blobs);
|
_code_roots.code_blobs_do(&blobsCl, worker_id);
|
||||||
}
|
|
||||||
|
|
||||||
if (ShenandoahStringDedup::is_enabled()) {
|
_weak_roots.oops_do<AlwaysTrueClosure, OopClosure>(&always_true, oops, worker_id);
|
||||||
ShenandoahStringDedup::parallel_oops_do(&always_true, oops, worker_id);
|
_dedup_roots.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 {
|
ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool update_code_cache) :
|
||||||
return _srs.n_threads();
|
ShenandoahRootProcessor(phase),
|
||||||
|
_thread_roots(n_workers > 1),
|
||||||
|
_weak_roots(n_workers),
|
||||||
|
_update_code_cache(update_code_cache) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implemenation of ParallelCLDRootIterator
|
ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
|
||||||
ParallelCLDRootIterator::ParallelCLDRootIterator() {
|
ShenandoahRootProcessor(phase),
|
||||||
assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint");
|
_thread_roots(n_workers > 1),
|
||||||
ClassLoaderDataGraph::clear_claimed_marks();
|
_weak_roots(n_workers) {
|
||||||
|
assert(ShenandoahHeap::heap()->is_full_gc_in_progress(), "Full GC only");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParallelCLDRootIterator::root_cld_do(CLDClosure* strong, CLDClosure* weak) {
|
void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) {
|
||||||
ClassLoaderDataGraph::roots_cld_do(strong, weak);
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,110 +36,160 @@
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
#include "memory/iterator.hpp"
|
#include "memory/iterator.hpp"
|
||||||
|
|
||||||
class ParallelCLDRootIterator {
|
class ShenandoahSerialRoot {
|
||||||
public:
|
public:
|
||||||
ParallelCLDRootIterator();
|
typedef void (*OopsDo)(OopClosure*);
|
||||||
void root_cld_do(CLDClosure* strong, CLDClosure* weak);
|
private:
|
||||||
|
volatile bool _claimed;
|
||||||
|
const OopsDo _oops_do;
|
||||||
|
const ShenandoahPhaseTimings::GCParPhases _phase;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ShenandoahSerialRoot(OopsDo oops_do, ShenandoahPhaseTimings::GCParPhases);
|
||||||
|
void oops_do(OopClosure* cl, uint worker_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Shenandoah_process_roots_tasks {
|
class ShenandoahSerialRoots {
|
||||||
SHENANDOAH_RP_PS_Universe_oops_do,
|
private:
|
||||||
SHENANDOAH_RP_PS_JNIHandles_oops_do,
|
ShenandoahSerialRoot _universe_root;
|
||||||
SHENANDOAH_RP_PS_ObjectSynchronizer_oops_do,
|
ShenandoahSerialRoot _object_synchronizer_root;
|
||||||
SHENANDOAH_RP_PS_Management_oops_do,
|
ShenandoahSerialRoot _management_root;
|
||||||
SHENANDOAH_RP_PS_SystemDictionary_oops_do,
|
ShenandoahSerialRoot _system_dictionary_root;
|
||||||
SHENANDOAH_RP_PS_jvmti_oops_do,
|
ShenandoahSerialRoot _jvmti_root;
|
||||||
// Leave this one last.
|
ShenandoahSerialRoot _jni_handle_root;
|
||||||
SHENANDOAH_RP_PS_NumElements
|
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);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShenandoahWeakRoots {
|
||||||
|
private:
|
||||||
|
WeakProcessorPhaseTimes _process_timings;
|
||||||
|
WeakProcessor::Task _task;
|
||||||
|
public:
|
||||||
|
ShenandoahWeakRoots(uint n_workers);
|
||||||
|
~ShenandoahWeakRoots();
|
||||||
|
|
||||||
|
template <typename IsAlive, typename KeepAlive>
|
||||||
|
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 <typename ITR>
|
||||||
|
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 {
|
class ShenandoahRootProcessor : public StackObj {
|
||||||
SubTasksDone* _process_strong_tasks;
|
private:
|
||||||
StrongRootsScope _srs;
|
ShenandoahHeap* const _heap;
|
||||||
ShenandoahPhaseTimings::Phase _phase;
|
const 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;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ShenandoahRootProcessor(ShenandoahHeap* heap, uint n_workers,
|
ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase);
|
||||||
ShenandoahPhaseTimings::Phase phase);
|
|
||||||
~ShenandoahRootProcessor();
|
~ShenandoahRootProcessor();
|
||||||
|
|
||||||
// Apply oops, clds and blobs to all strongly reachable roots in the system.
|
ShenandoahHeap* heap() const { return _heap; }
|
||||||
// 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);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Apply oops, clds and blobs to strongly and weakly reachable roots in the system
|
|
||||||
template <typename IsAlive>
|
|
||||||
void update_all_roots(OopClosure* oops,
|
|
||||||
CLDClosure* clds,
|
|
||||||
CodeBlobClosure* blobs,
|
|
||||||
ThreadClosure* thread_cl,
|
|
||||||
uint worker_id);
|
|
||||||
|
|
||||||
// Number of worker threads used by the root processor.
|
|
||||||
uint n_workers() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ShenandoahRootEvacuator : public StackObj {
|
class ShenandoahRootScanner : public ShenandoahRootProcessor {
|
||||||
SubTasksDone* _evacuation_tasks;
|
private:
|
||||||
StrongRootsScope _srs;
|
ShenandoahSerialRoots _serial_roots;
|
||||||
ShenandoahPhaseTimings::Phase _phase;
|
ShenandoahClassLoaderDataRoots _cld_roots;
|
||||||
ShenandoahCsetCodeRootsIterator _coderoots_cset_iterator;
|
ShenandoahThreadRoots _thread_roots;
|
||||||
ParallelCLDRootIterator _cld_iterator;
|
ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator> _code_roots;
|
||||||
WeakProcessorPhaseTimes _weak_processor_timings;
|
|
||||||
WeakProcessor::Task _weak_processor_task;
|
|
||||||
|
|
||||||
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
|
|
||||||
};
|
|
||||||
public:
|
public:
|
||||||
ShenandoahRootEvacuator(ShenandoahHeap* heap, uint n_workers,
|
ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
|
||||||
ShenandoahPhaseTimings::Phase phase);
|
|
||||||
~ShenandoahRootEvacuator();
|
|
||||||
|
|
||||||
void process_evacuate_roots(OopClosure* oops,
|
// Apply oops, clds and blobs to all strongly reachable roots in the system,
|
||||||
CodeBlobClosure* blobs,
|
// during class unloading cycle
|
||||||
uint worker_id);
|
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.
|
// Apply oops, clds and blobs to all strongly reachable roots and weakly reachable
|
||||||
uint n_workers() const;
|
// 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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 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<ShenandoahCsetCodeRootsIterator> _code_roots;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase);
|
||||||
|
|
||||||
|
void roots_do(uint worker_id, OopClosure* oops);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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<ShenandoahCsetCodeRootsIterator> _code_roots;
|
||||||
|
const bool _update_code_cache;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool update_code_cache);
|
||||||
|
|
||||||
|
template<typename IsAlive, typename KeepAlive>
|
||||||
|
void roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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<ShenandoahAllCodeRootsIterator> _code_roots;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase);
|
||||||
|
|
||||||
|
void roots_do(uint worker_id, OopClosure* oops);
|
||||||
|
};
|
||||||
|
|
||||||
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP
|
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP
|
||||||
|
|
|
@ -25,22 +25,47 @@
|
||||||
#define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP
|
#define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP
|
||||||
|
|
||||||
#include "gc/shenandoah/shenandoahRootProcessor.hpp"
|
#include "gc/shenandoah/shenandoahRootProcessor.hpp"
|
||||||
|
#include "gc/shenandoah/shenandoahTimingTracker.hpp"
|
||||||
|
|
||||||
template <typename IsAlive>
|
template <typename IsAlive, typename KeepAlive>
|
||||||
void ShenandoahRootProcessor::update_all_roots(OopClosure* oops,
|
void ShenandoahWeakRoots::oops_do(IsAlive* is_alive, KeepAlive* keep_alive, uint worker_id) {
|
||||||
CLDClosure* clds,
|
_task.work<IsAlive, KeepAlive>(worker_id, is_alive, keep_alive);
|
||||||
CodeBlobClosure* blobs,
|
}
|
||||||
ThreadClosure* thread_cl,
|
|
||||||
uint worker_id) {
|
|
||||||
process_all_roots(oops, clds, blobs, thread_cl, worker_id);
|
|
||||||
|
|
||||||
IsAlive is_alive;
|
template <typename ITR>
|
||||||
_weak_processor_task.work<IsAlive, OopClosure>(worker_id, &is_alive, oops);
|
ShenandoahCodeCacheRoots<ITR>::ShenandoahCodeCacheRoots() {
|
||||||
_processed_weak_roots = true;
|
nmethod::oops_do_marking_prologue();
|
||||||
|
}
|
||||||
|
|
||||||
if (ShenandoahStringDedup::is_enabled()) {
|
template <typename ITR>
|
||||||
ShenandoahStringDedup::parallel_oops_do(&is_alive, oops, worker_id);
|
void ShenandoahCodeCacheRoots<ITR>::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);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ITR>
|
||||||
|
ShenandoahCodeCacheRoots<ITR>::~ShenandoahCodeCacheRoots() {
|
||||||
|
nmethod::oops_do_marking_epilogue();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename IsAlive, typename KeepAlive>
|
||||||
|
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;
|
||||||
|
|
||||||
|
_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<IsAlive, KeepAlive>(is_alive, keep_alive, worker_id);
|
||||||
|
_dedup_roots.oops_do(is_alive, keep_alive, worker_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP
|
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP
|
||||||
|
|
|
@ -161,11 +161,13 @@ public:
|
||||||
|
|
||||||
class ShenandoahInitTraversalCollectionTask : public AbstractGangTask {
|
class ShenandoahInitTraversalCollectionTask : public AbstractGangTask {
|
||||||
private:
|
private:
|
||||||
ShenandoahRootProcessor* _rp;
|
ShenandoahRootScanner* _rp;
|
||||||
ShenandoahHeap* _heap;
|
ShenandoahHeap* _heap;
|
||||||
ShenandoahCsetCodeRootsIterator* _cset_coderoots;
|
ShenandoahCsetCodeRootsIterator* _cset_coderoots;
|
||||||
|
ShenandoahStringDedupRoots _dedup_roots;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ShenandoahInitTraversalCollectionTask(ShenandoahRootProcessor* rp, ShenandoahCsetCodeRootsIterator* cset_coderoots) :
|
ShenandoahInitTraversalCollectionTask(ShenandoahRootScanner* rp, ShenandoahCsetCodeRootsIterator* cset_coderoots) :
|
||||||
AbstractGangTask("Shenandoah Init Traversal Collection"),
|
AbstractGangTask("Shenandoah Init Traversal Collection"),
|
||||||
_rp(rp),
|
_rp(rp),
|
||||||
_heap(ShenandoahHeap::heap()),
|
_heap(ShenandoahHeap::heap()),
|
||||||
|
@ -191,18 +193,17 @@ public:
|
||||||
ShenandoahMarkCLDClosure cld_cl(&roots_cl);
|
ShenandoahMarkCLDClosure cld_cl(&roots_cl);
|
||||||
MarkingCodeBlobClosure code_cl(&roots_cl, CodeBlobToOopClosure::FixRelocations);
|
MarkingCodeBlobClosure code_cl(&roots_cl, CodeBlobToOopClosure::FixRelocations);
|
||||||
if (unload_classes) {
|
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.
|
// Need to pre-evac code roots here. Otherwise we might see from-space constants.
|
||||||
ShenandoahWorkerTimings* worker_times = _heap->phase_timings()->worker_times();
|
ShenandoahWorkerTimings* worker_times = _heap->phase_timings()->worker_times();
|
||||||
ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id);
|
ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id);
|
||||||
_cset_coderoots->possibly_parallel_blobs_do(&code_cl);
|
_cset_coderoots->possibly_parallel_blobs_do(&code_cl);
|
||||||
} else {
|
} 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 @@ public:
|
||||||
|
|
||||||
class ShenandoahFinalTraversalCollectionTask : public AbstractGangTask {
|
class ShenandoahFinalTraversalCollectionTask : public AbstractGangTask {
|
||||||
private:
|
private:
|
||||||
ShenandoahRootProcessor* _rp;
|
ShenandoahRootScanner* _rp;
|
||||||
ShenandoahTaskTerminator* _terminator;
|
ShenandoahTaskTerminator* _terminator;
|
||||||
ShenandoahHeap* _heap;
|
ShenandoahHeap* _heap;
|
||||||
public:
|
public:
|
||||||
ShenandoahFinalTraversalCollectionTask(ShenandoahRootProcessor* rp, ShenandoahTaskTerminator* terminator) :
|
ShenandoahFinalTraversalCollectionTask(ShenandoahRootScanner* rp, ShenandoahTaskTerminator* terminator) :
|
||||||
AbstractGangTask("Shenandoah Final Traversal Collection"),
|
AbstractGangTask("Shenandoah Final Traversal Collection"),
|
||||||
_rp(rp),
|
_rp(rp),
|
||||||
_terminator(terminator),
|
_terminator(terminator),
|
||||||
|
@ -273,23 +274,23 @@ public:
|
||||||
// roots here.
|
// roots here.
|
||||||
if (!_heap->is_degenerated_gc_in_progress()) {
|
if (!_heap->is_degenerated_gc_in_progress()) {
|
||||||
ShenandoahTraversalClosure roots_cl(q, rp);
|
ShenandoahTraversalClosure roots_cl(q, rp);
|
||||||
CLDToOopClosure cld_cl(&roots_cl, ClassLoaderData::_claim_strong);
|
|
||||||
ShenandoahTraversalSATBThreadsClosure tc(&satb_cl);
|
ShenandoahTraversalSATBThreadsClosure tc(&satb_cl);
|
||||||
if (unload_classes) {
|
if (unload_classes) {
|
||||||
ShenandoahRemarkCLDClosure remark_cld_cl(&roots_cl);
|
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 {
|
} 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 {
|
} else {
|
||||||
ShenandoahTraversalDegenClosure roots_cl(q, rp);
|
ShenandoahTraversalDegenClosure roots_cl(q, rp);
|
||||||
CLDToOopClosure cld_cl(&roots_cl, ClassLoaderData::_claim_strong);
|
|
||||||
ShenandoahTraversalSATBThreadsClosure tc(&satb_cl);
|
ShenandoahTraversalSATBThreadsClosure tc(&satb_cl);
|
||||||
if (unload_classes) {
|
if (unload_classes) {
|
||||||
ShenandoahRemarkCLDClosure remark_cld_cl(&roots_cl);
|
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 {
|
} 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 @@ ShenandoahTraversalGC::ShenandoahTraversalGC(ShenandoahHeap* heap, size_t num_re
|
||||||
_task_queues(new ShenandoahObjToScanQueueSet(heap->max_workers())),
|
_task_queues(new ShenandoahObjToScanQueueSet(heap->max_workers())),
|
||||||
_traversal_set(ShenandoahHeapRegionSet()) {
|
_traversal_set(ShenandoahHeapRegionSet()) {
|
||||||
|
|
||||||
|
// Traversal does not support concurrent code root scanning
|
||||||
|
FLAG_SET_DEFAULT(ShenandoahConcurrentScanCodeRoots, false);
|
||||||
|
|
||||||
uint num_queues = heap->max_workers();
|
uint num_queues = heap->max_workers();
|
||||||
for (uint i = 0; i < num_queues; ++i) {
|
for (uint i = 0; i < num_queues; ++i) {
|
||||||
ShenandoahObjToScanQueue* task_queue = new ShenandoahObjToScanQueue();
|
ShenandoahObjToScanQueue* task_queue = new ShenandoahObjToScanQueue();
|
||||||
|
@ -411,7 +415,7 @@ void ShenandoahTraversalGC::init_traversal_collection() {
|
||||||
{
|
{
|
||||||
uint nworkers = _heap->workers()->active_workers();
|
uint nworkers = _heap->workers()->active_workers();
|
||||||
task_queues()->reserve(nworkers);
|
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();
|
ShenandoahCsetCodeRootsIterator cset_coderoots = ShenandoahCodeRoots::cset_iterator();
|
||||||
|
|
||||||
|
@ -584,7 +588,7 @@ void ShenandoahTraversalGC::final_traversal_collection() {
|
||||||
task_queues()->reserve(nworkers);
|
task_queues()->reserve(nworkers);
|
||||||
|
|
||||||
// Finish traversal
|
// 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);
|
ShenandoahTerminationTracker term(ShenandoahPhaseTimings::final_traversal_gc_termination);
|
||||||
|
|
||||||
ShenandoahTaskTerminator terminator(nworkers, task_queues());
|
ShenandoahTaskTerminator terminator(nworkers, task_queues());
|
||||||
|
@ -693,10 +697,10 @@ public:
|
||||||
|
|
||||||
class ShenandoahTraversalFixRootsTask : public AbstractGangTask {
|
class ShenandoahTraversalFixRootsTask : public AbstractGangTask {
|
||||||
private:
|
private:
|
||||||
ShenandoahRootProcessor* _rp;
|
ShenandoahRootUpdater* _rp;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ShenandoahTraversalFixRootsTask(ShenandoahRootProcessor* rp) :
|
ShenandoahTraversalFixRootsTask(ShenandoahRootUpdater* rp) :
|
||||||
AbstractGangTask("Shenandoah traversal fix roots"),
|
AbstractGangTask("Shenandoah traversal fix roots"),
|
||||||
_rp(rp) {
|
_rp(rp) {
|
||||||
assert(ShenandoahHeap::heap()->has_forwarded_objects(), "Must be");
|
assert(ShenandoahHeap::heap()->has_forwarded_objects(), "Must be");
|
||||||
|
@ -705,9 +709,8 @@ public:
|
||||||
void work(uint worker_id) {
|
void work(uint worker_id) {
|
||||||
ShenandoahParallelWorkerSession worker_session(worker_id);
|
ShenandoahParallelWorkerSession worker_session(worker_id);
|
||||||
ShenandoahTraversalFixRootsClosure cl;
|
ShenandoahTraversalFixRootsClosure cl;
|
||||||
MarkingCodeBlobClosure blobsCl(&cl, CodeBlobToOopClosure::FixRelocations);
|
ShenandoahForwardedIsAliveClosure is_alive;
|
||||||
CLDToOopClosure cldCl(&cl, ClassLoaderData::_claim_strong);
|
_rp->roots_do<ShenandoahForwardedIsAliveClosure, ShenandoahTraversalFixRootsClosure>(worker_id, &is_alive, &cl);
|
||||||
_rp->update_all_roots<ShenandoahForwardedIsAliveClosure>(&cl, &cldCl, &blobsCl, NULL, worker_id);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -715,7 +718,7 @@ void ShenandoahTraversalGC::fixup_roots() {
|
||||||
#if defined(COMPILER2) || INCLUDE_JVMCI
|
#if defined(COMPILER2) || INCLUDE_JVMCI
|
||||||
DerivedPointerTable::clear();
|
DerivedPointerTable::clear();
|
||||||
#endif
|
#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);
|
ShenandoahTraversalFixRootsTask update_roots_task(&rp);
|
||||||
_heap->workers()->run_task(&update_roots_task);
|
_heap->workers()->run_task(&update_roots_task);
|
||||||
#if defined(COMPILER2) || INCLUDE_JVMCI
|
#if defined(COMPILER2) || INCLUDE_JVMCI
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue