Skip to content
Permalink
Browse files
8273559: Shenandoah: Shenandoah should support multi-threaded heap dump
Reviewed-by: shade, rkennke, sgehwolf
  • Loading branch information
zhengyu123 committed Sep 15, 2021
1 parent f531b5c commit 8132bfd23f2f7fb52e502a3e6fe488fbdb537df0
@@ -725,7 +725,7 @@ class ShenandoahConcurrentWeakRootsEvacUpdateTask : public AbstractGangTask {
ShenandoahVMWeakRoots<true /*concurrent*/> _vm_roots;

// Roots related to concurrent class unloading
ShenandoahClassLoaderDataRoots<true /* concurrent */, true /* single thread*/>
ShenandoahClassLoaderDataRoots<true /* concurrent */>
_cld_roots;
ShenandoahConcurrentNMethodIterator _nmethod_itr;
ShenandoahPhaseTimings::Phase _phase;
@@ -734,7 +734,7 @@ class ShenandoahConcurrentWeakRootsEvacUpdateTask : public AbstractGangTask {
ShenandoahConcurrentWeakRootsEvacUpdateTask(ShenandoahPhaseTimings::Phase phase) :
AbstractGangTask("Shenandoah Evacuate/Update Concurrent Weak Roots"),
_vm_roots(phase),
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers()),
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers(), false /*heap iteration*/),
_nmethod_itr(ShenandoahCodeRoots::table()),
_phase(phase) {
if (ShenandoahHeap::heap()->unload_classes()) {
@@ -838,15 +838,16 @@ class ShenandoahConcurrentRootsEvacUpdateTask : public AbstractGangTask {
private:
ShenandoahPhaseTimings::Phase _phase;
ShenandoahVMRoots<true /*concurrent*/> _vm_roots;
ShenandoahClassLoaderDataRoots<true /*concurrent*/, false /*single threaded*/> _cld_roots;
ShenandoahClassLoaderDataRoots<true /*concurrent*/>
_cld_roots;
ShenandoahConcurrentNMethodIterator _nmethod_itr;

public:
ShenandoahConcurrentRootsEvacUpdateTask(ShenandoahPhaseTimings::Phase phase) :
AbstractGangTask("Shenandoah Evacuate/Update Concurrent Strong Roots"),
_phase(phase),
_vm_roots(phase),
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers()),
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers(), false /*heap iteration*/),
_nmethod_itr(ShenandoahCodeRoots::table()) {
if (!ShenandoahHeap::heap()->unload_classes()) {
MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
@@ -1317,7 +1317,8 @@ void ShenandoahHeap::scan_roots_for_iteration(ShenandoahScanObjectStack* oop_sta
// This populates the work stack with initial objects
// It is important to relinquish the associated locks before diving
// into heap dumper
ShenandoahHeapIterationRootScanner rp;
uint n_workers = safepoint_workers() != NULL ? safepoint_workers()->active_workers() : 1;
ShenandoahHeapIterationRootScanner rp(n_workers);
rp.roots_do(oops);
}

@@ -124,7 +124,7 @@ ShenandoahSTWRootScanner::ShenandoahSTWRootScanner(ShenandoahPhaseTimings::Phase
ShenandoahRootProcessor(phase),
_thread_roots(phase, ShenandoahHeap::heap()->workers()->active_workers() > 1),
_code_roots(phase),
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers()),
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers(), false /*heap iteration*/),
_vm_roots(phase),
_unload_classes(ShenandoahHeap::heap()->unload_classes()) {
}
@@ -154,7 +154,7 @@ ShenandoahConcurrentRootScanner::ShenandoahConcurrentRootScanner(uint n_workers,
ShenandoahRootProcessor(phase),
_java_threads(phase, n_workers),
_vm_roots(phase),
_cld_roots(phase, n_workers),
_cld_roots(phase, n_workers, false /*heap iteration*/),
_codecache_snapshot(NULL),
_phase(phase) {
if (!ShenandoahHeap::heap()->unload_classes()) {
@@ -213,7 +213,7 @@ void ShenandoahConcurrentRootScanner::update_tlab_stats() {
ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
ShenandoahRootProcessor(phase),
_vm_roots(phase),
_cld_roots(phase, n_workers),
_cld_roots(phase, n_workers, false /*heap iteration*/),
_thread_roots(phase, n_workers > 1),
_weak_roots(phase),
_code_roots(phase) {
@@ -222,7 +222,7 @@ ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimi
ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
ShenandoahRootProcessor(phase),
_vm_roots(phase),
_cld_roots(phase, n_workers),
_cld_roots(phase, n_workers, false /*heap iteration*/),
_thread_roots(phase, n_workers > 1),
_weak_roots(phase),
_code_roots(phase) {
@@ -248,18 +248,18 @@ void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) {
_thread_roots.oops_do(oops, NULL, worker_id);
}

ShenandoahHeapIterationRootScanner::ShenandoahHeapIterationRootScanner() :
ShenandoahHeapIterationRootScanner::ShenandoahHeapIterationRootScanner(uint n_workers) :
ShenandoahRootProcessor(ShenandoahPhaseTimings::heap_iteration_roots),
_thread_roots(ShenandoahPhaseTimings::heap_iteration_roots, false /*is par*/),
_vm_roots(ShenandoahPhaseTimings::heap_iteration_roots),
_cld_roots(ShenandoahPhaseTimings::heap_iteration_roots, 1),
_cld_roots(ShenandoahPhaseTimings::heap_iteration_roots, n_workers, true /*heap iteration*/),
_weak_roots(ShenandoahPhaseTimings::heap_iteration_roots),
_code_roots(ShenandoahPhaseTimings::heap_iteration_roots) {
}

void ShenandoahHeapIterationRootScanner::roots_do(OopClosure* oops) {
// Must use _claim_none to avoid interfering with concurrent CLDG iteration
CLDToOopClosure clds(oops, ClassLoaderData::_claim_none);
// Must use _claim_other to avoid interfering with concurrent CLDG iteration
CLDToOopClosure clds(oops, ClassLoaderData::_claim_other);
MarkingCodeBlobClosure code(oops, !CodeBlobToOopClosure::FixRelocations);
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, &code, NULL);
AlwaysTrueClosure always_true;
@@ -107,23 +107,21 @@ class ShenandoahCodeCacheRoots {
void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id);
};

template <bool CONCURRENT, bool SINGLE_THREADED>
template <bool CONCURRENT>
class ShenandoahClassLoaderDataRoots {
private:
ShenandoahSharedSemaphore _semaphore;
ShenandoahPhaseTimings::Phase _phase;

static uint worker_count(uint n_workers) {
if (SINGLE_THREADED) return 1u;

// Limit concurrency a bit, otherwise it wastes resources when workers are tripping
// over each other. This also leaves free workers to process other parts of the root
// set, while admitted workers are busy with doing the CLDG walk.
return MAX2(1u, MIN2(ShenandoahSharedSemaphore::max_tokens(), n_workers / 2));
}

public:
ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers);
ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers, bool heap_iteration);
~ShenandoahClassLoaderDataRoots();

void always_strong_cld_do(CLDClosure* clds, uint worker_id);
@@ -164,7 +162,7 @@ class ShenandoahSTWRootScanner : public ShenandoahRootProcessor {
private:
ShenandoahThreadRoots _thread_roots;
ShenandoahCodeCacheRoots _code_roots;
ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /* single_thread*/>
ShenandoahClassLoaderDataRoots<false /*concurrent*/>
_cld_roots;
ShenandoahVMRoots<false /*concurrent*/>
_vm_roots;
@@ -180,7 +178,7 @@ class ShenandoahConcurrentRootScanner : public ShenandoahRootProcessor {
private:
ShenandoahJavaThreadsIterator _java_threads;
ShenandoahVMRoots<true /*concurrent*/> _vm_roots;
ShenandoahClassLoaderDataRoots<true /*concurrent*/, false /* single-threaded*/>
ShenandoahClassLoaderDataRoots<true /*concurrent*/>
_cld_roots;
ShenandoahNMethodTableSnapshot* _codecache_snapshot;
ShenandoahPhaseTimings::Phase _phase;
@@ -201,13 +199,12 @@ class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor {
private:
ShenandoahThreadRoots _thread_roots;
ShenandoahVMRoots<false /*concurrent*/> _vm_roots;
ShenandoahClassLoaderDataRoots<false /*concurrent*/, true /*single threaded*/>
_cld_roots;
ShenandoahClassLoaderDataRoots<false /*concurrent*/> _cld_roots;
ShenandoahVMWeakRoots<false /*concurrent*/> _weak_roots;
ShenandoahCodeCacheRoots _code_roots;

public:
ShenandoahHeapIterationRootScanner();
ShenandoahHeapIterationRootScanner(uint n_workers);

void roots_do(OopClosure* cl);
};
@@ -216,8 +213,7 @@ class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor {
class ShenandoahRootUpdater : public ShenandoahRootProcessor {
private:
ShenandoahVMRoots<false /*concurrent*/> _vm_roots;
ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
_cld_roots;
ShenandoahClassLoaderDataRoots<false /*concurrent*/> _cld_roots;
ShenandoahThreadRoots _thread_roots;
ShenandoahVMWeakRoots<false /*concurrent*/> _weak_roots;
ShenandoahCodeCacheRoots _code_roots;
@@ -233,8 +229,7 @@ class ShenandoahRootUpdater : public ShenandoahRootProcessor {
class ShenandoahRootAdjuster : public ShenandoahRootProcessor {
private:
ShenandoahVMRoots<false /*concurrent*/> _vm_roots;
ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
_cld_roots;
ShenandoahClassLoaderDataRoots<false /*concurrent*/> _cld_roots;
ShenandoahThreadRoots _thread_roots;
ShenandoahVMWeakRoots<false /*concurrent*/> _weak_roots;
ShenandoahCodeCacheRoots _code_roots;
@@ -75,39 +75,37 @@ void ShenandoahVMRoots<CONCURRENT>::oops_do(T* cl, uint worker_id) {
_strong_roots.oops_do(cl);
}

template <bool CONCURRENT, bool SINGLE_THREADED>
ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers) :
template <bool CONCURRENT>
ShenandoahClassLoaderDataRoots<CONCURRENT>::ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers, bool heap_iteration) :
_semaphore(worker_count(n_workers)),
_phase(phase) {
if (!SINGLE_THREADED) {
if (heap_iteration) {
ClassLoaderDataGraph::clear_claimed_marks(ClassLoaderData::_claim_other);
} else {
ClassLoaderDataGraph::clear_claimed_marks();
}
if (CONCURRENT && !SINGLE_THREADED) {

if (CONCURRENT) {
ClassLoaderDataGraph_lock->lock();
}

// Non-concurrent mode only runs at safepoints
assert(CONCURRENT || SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
}

template <bool CONCURRENT, bool SINGLE_THREADED>
ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::~ShenandoahClassLoaderDataRoots() {
if (CONCURRENT && !SINGLE_THREADED) {
template <bool CONCURRENT>
ShenandoahClassLoaderDataRoots<CONCURRENT>::~ShenandoahClassLoaderDataRoots() {
if (CONCURRENT) {
ClassLoaderDataGraph_lock->unlock();
}
}

template <bool CONCURRENT, bool SINGLE_THREADED>
void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::cld_do_impl(CldDo f, CLDClosure* clds, uint worker_id) {
template <bool CONCURRENT>
void ShenandoahClassLoaderDataRoots<CONCURRENT>::cld_do_impl(CldDo f, CLDClosure* clds, uint worker_id) {
if (CONCURRENT) {
if (_semaphore.try_acquire()) {
ShenandoahWorkerTimingsTracker timer(_phase, ShenandoahPhaseTimings::CLDGRoots, worker_id);
if (SINGLE_THREADED){
MutexLocker ml(ClassLoaderDataGraph_lock, Mutex::_no_safepoint_check_flag);
f(clds);
} else {
f(clds);
}
f(clds);
_semaphore.claim_all();
}
} else {
@@ -116,13 +114,13 @@ void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::cld_do_impl(Cl
}
}

template <bool CONCURRENT, bool SINGLE_THREADED>
void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::always_strong_cld_do(CLDClosure* clds, uint worker_id) {
template <bool CONCURRENT>
void ShenandoahClassLoaderDataRoots<CONCURRENT>::always_strong_cld_do(CLDClosure* clds, uint worker_id) {
cld_do_impl(&ClassLoaderDataGraph::always_strong_cld_do, clds, worker_id);
}

template <bool CONCURRENT, bool SINGLE_THREADED>
void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::cld_do(CLDClosure* clds, uint worker_id) {
template <bool CONCURRENT>
void ShenandoahClassLoaderDataRoots<CONCURRENT>::cld_do(CLDClosure* clds, uint worker_id) {
cld_do_impl(&ClassLoaderDataGraph::cld_do, clds, worker_id);
}

Loading

1 comment on commit 8132bfd

@openjdk-notifier

This comment has been minimized.

Copy link

@openjdk-notifier openjdk-notifier bot commented on 8132bfd Sep 15, 2021

Please sign in to comment.