mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-19 18:44:38 +02:00
8226413: Shenandoah: Separate root scanner for SH::object_iterate()
Reviewed-by: rkennke
This commit is contained in:
parent
3c29fa1203
commit
cd130d9b39
4 changed files with 93 additions and 59 deletions
|
@ -1279,14 +1279,14 @@ 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 GC roots according to current GC cycle. This populates the work stack with initial objects.
|
||||||
ShenandoahAllRootScanner rp(1, ShenandoahPhaseTimings::_num_phases);
|
ShenandoahHeapIterationRootScanner rp;
|
||||||
ObjectIterateScanRootClosure oops(&_aux_bit_map, &oop_stack);
|
ObjectIterateScanRootClosure oops(&_aux_bit_map, &oop_stack);
|
||||||
|
|
||||||
if (unload_classes()) {
|
if (unload_classes()) {
|
||||||
rp.strong_roots_do_unchecked(&oops);
|
rp.strong_roots_do(&oops);
|
||||||
} else {
|
} else {
|
||||||
rp.roots_do_unchecked(&oops);
|
rp.roots_do(&oops);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Work through the oop stack to traverse heap.
|
// Work through the oop stack to traverse heap.
|
||||||
|
@ -1587,7 +1587,7 @@ void ShenandoahHeap::op_cleanup() {
|
||||||
|
|
||||||
class ShenandoahConcurrentRootsEvacUpdateTask : public AbstractGangTask {
|
class ShenandoahConcurrentRootsEvacUpdateTask : public AbstractGangTask {
|
||||||
private:
|
private:
|
||||||
ShenandoahJNIHandleRoots<true /*concurrent*/> _jni_roots;
|
ShenandoahJNIHandleRoots<true /*concurrent*/> _jni_roots;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ShenandoahConcurrentRootsEvacUpdateTask() :
|
ShenandoahConcurrentRootsEvacUpdateTask() :
|
||||||
|
|
|
@ -122,16 +122,6 @@ void ShenandoahStringDedupRoots::oops_do(BoolObjectClosure* is_alive, OopClosure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) :
|
ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase) :
|
||||||
_heap(ShenandoahHeap::heap()),
|
_heap(ShenandoahHeap::heap()),
|
||||||
_phase(phase) {
|
_phase(phase) {
|
||||||
|
@ -198,3 +188,37 @@ void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) {
|
||||||
_weak_roots.oops_do<AlwaysTrueClosure, OopClosure>(&always_true, oops, worker_id);
|
_weak_roots.oops_do<AlwaysTrueClosure, OopClosure>(&always_true, oops, worker_id);
|
||||||
_dedup_roots.oops_do(&always_true, oops, worker_id);
|
_dedup_roots.oops_do(&always_true, oops, worker_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShenandoahHeapIterationRootScanner::ShenandoahHeapIterationRootScanner() :
|
||||||
|
ShenandoahRootProcessor(ShenandoahPhaseTimings::_num_phases),
|
||||||
|
_thread_roots(false /*is par*/) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShenandoahHeapIterationRootScanner::roots_do(OopClosure* oops) {
|
||||||
|
assert(Thread::current()->is_VM_thread(), "Only by VM thread");
|
||||||
|
// Must use _claim_none to avoid interfering with concurrent CLDG iteration
|
||||||
|
CLDToOopClosure clds(oops, ClassLoaderData::_claim_none);
|
||||||
|
MarkingCodeBlobClosure code(oops, !CodeBlobToOopClosure::FixRelocations);
|
||||||
|
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, &code, NULL);
|
||||||
|
ResourceMark rm;
|
||||||
|
|
||||||
|
_serial_roots.oops_do(oops, 0);
|
||||||
|
_jni_roots.oops_do(oops, 0);
|
||||||
|
_cld_roots.clds_do(&clds, &clds, 0);
|
||||||
|
_thread_roots.threads_do(&tc_cl, 0);
|
||||||
|
_code_roots.code_blobs_do(&code, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShenandoahHeapIterationRootScanner::strong_roots_do(OopClosure* oops) {
|
||||||
|
assert(Thread::current()->is_VM_thread(), "Only by VM thread");
|
||||||
|
// Must use _claim_none to avoid interfering with concurrent CLDG iteration
|
||||||
|
CLDToOopClosure clds(oops, ClassLoaderData::_claim_none);
|
||||||
|
MarkingCodeBlobClosure code(oops, !CodeBlobToOopClosure::FixRelocations);
|
||||||
|
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, &code, NULL);
|
||||||
|
ResourceMark rm;
|
||||||
|
|
||||||
|
_serial_roots.oops_do(oops, 0);
|
||||||
|
_jni_roots.oops_do(oops, 0);
|
||||||
|
_cld_roots.clds_do(&clds, NULL, 0);
|
||||||
|
_thread_roots.threads_do(&tc_cl, 0);
|
||||||
|
}
|
||||||
|
|
|
@ -114,6 +114,7 @@ public:
|
||||||
void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id);
|
void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <bool SINGLE_THREADED>
|
||||||
class ShenandoahClassLoaderDataRoots {
|
class ShenandoahClassLoaderDataRoots {
|
||||||
public:
|
public:
|
||||||
ShenandoahClassLoaderDataRoots();
|
ShenandoahClassLoaderDataRoots();
|
||||||
|
@ -135,11 +136,11 @@ public:
|
||||||
template <typename ITR>
|
template <typename ITR>
|
||||||
class ShenandoahRootScanner : public ShenandoahRootProcessor {
|
class ShenandoahRootScanner : public ShenandoahRootProcessor {
|
||||||
private:
|
private:
|
||||||
ShenandoahSerialRoots _serial_roots;
|
ShenandoahSerialRoots _serial_roots;
|
||||||
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
|
ShenandoahThreadRoots _thread_roots;
|
||||||
ShenandoahClassLoaderDataRoots _cld_roots;
|
ShenandoahCodeCacheRoots<ITR> _code_roots;
|
||||||
ShenandoahThreadRoots _thread_roots;
|
ShenandoahJNIHandleRoots<false /*concurrent*/ > _jni_roots;
|
||||||
ShenandoahCodeCacheRoots<ITR> _code_roots;
|
ShenandoahClassLoaderDataRoots<false /*single threaded*/> _cld_roots;
|
||||||
public:
|
public:
|
||||||
ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
|
ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
|
||||||
|
|
||||||
|
@ -152,20 +153,34 @@ public:
|
||||||
// roots when class unloading is disabled during this cycle
|
// roots when class unloading is disabled during this cycle
|
||||||
void roots_do(uint worker_id, OopClosure* cl);
|
void roots_do(uint worker_id, OopClosure* cl);
|
||||||
void roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL);
|
void roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL);
|
||||||
// For heap object iteration
|
|
||||||
void roots_do_unchecked(OopClosure* cl);
|
|
||||||
void strong_roots_do_unchecked(OopClosure* cl);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef ShenandoahRootScanner<ShenandoahAllCodeRootsIterator> ShenandoahAllRootScanner;
|
typedef ShenandoahRootScanner<ShenandoahAllCodeRootsIterator> ShenandoahAllRootScanner;
|
||||||
typedef ShenandoahRootScanner<ShenandoahCsetCodeRootsIterator> ShenandoahCSetRootScanner;
|
typedef ShenandoahRootScanner<ShenandoahCsetCodeRootsIterator> ShenandoahCSetRootScanner;
|
||||||
|
|
||||||
|
// This scanner is only for SH::object_iteration() and only supports single-threaded
|
||||||
|
// root scanning
|
||||||
|
class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor {
|
||||||
|
private:
|
||||||
|
ShenandoahSerialRoots _serial_roots;
|
||||||
|
ShenandoahThreadRoots _thread_roots;
|
||||||
|
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
|
||||||
|
ShenandoahClassLoaderDataRoots<true /*single threaded*/> _cld_roots;
|
||||||
|
ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator> _code_roots;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ShenandoahHeapIterationRootScanner();
|
||||||
|
|
||||||
|
void roots_do(OopClosure* cl);
|
||||||
|
void strong_roots_do(OopClosure* cl);
|
||||||
|
};
|
||||||
|
|
||||||
// Evacuate all roots at a safepoint
|
// Evacuate all roots at a safepoint
|
||||||
class ShenandoahRootEvacuator : public ShenandoahRootProcessor {
|
class ShenandoahRootEvacuator : public ShenandoahRootProcessor {
|
||||||
private:
|
private:
|
||||||
ShenandoahSerialRoots _serial_roots;
|
ShenandoahSerialRoots _serial_roots;
|
||||||
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
|
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
|
||||||
ShenandoahClassLoaderDataRoots _cld_roots;
|
ShenandoahClassLoaderDataRoots<false /*single threaded*/> _cld_roots;
|
||||||
ShenandoahThreadRoots _thread_roots;
|
ShenandoahThreadRoots _thread_roots;
|
||||||
ShenandoahWeakRoots _weak_roots;
|
ShenandoahWeakRoots _weak_roots;
|
||||||
ShenandoahStringDedupRoots _dedup_roots;
|
ShenandoahStringDedupRoots _dedup_roots;
|
||||||
|
@ -183,7 +198,7 @@ class ShenandoahRootUpdater : public ShenandoahRootProcessor {
|
||||||
private:
|
private:
|
||||||
ShenandoahSerialRoots _serial_roots;
|
ShenandoahSerialRoots _serial_roots;
|
||||||
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
|
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
|
||||||
ShenandoahClassLoaderDataRoots _cld_roots;
|
ShenandoahClassLoaderDataRoots<false /*single threaded*/> _cld_roots;
|
||||||
ShenandoahThreadRoots _thread_roots;
|
ShenandoahThreadRoots _thread_roots;
|
||||||
ShenandoahWeakRoots _weak_roots;
|
ShenandoahWeakRoots _weak_roots;
|
||||||
ShenandoahStringDedupRoots _dedup_roots;
|
ShenandoahStringDedupRoots _dedup_roots;
|
||||||
|
@ -200,13 +215,13 @@ public:
|
||||||
// Adjuster all roots at a safepoint during full gc
|
// Adjuster all roots at a safepoint during full gc
|
||||||
class ShenandoahRootAdjuster : public ShenandoahRootProcessor {
|
class ShenandoahRootAdjuster : public ShenandoahRootProcessor {
|
||||||
private:
|
private:
|
||||||
ShenandoahSerialRoots _serial_roots;
|
ShenandoahSerialRoots _serial_roots;
|
||||||
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
|
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
|
||||||
ShenandoahClassLoaderDataRoots _cld_roots;
|
ShenandoahClassLoaderDataRoots<false /*single threaded*/> _cld_roots;
|
||||||
ShenandoahThreadRoots _thread_roots;
|
ShenandoahThreadRoots _thread_roots;
|
||||||
ShenandoahWeakRoots _weak_roots;
|
ShenandoahWeakRoots _weak_roots;
|
||||||
ShenandoahStringDedupRoots _dedup_roots;
|
ShenandoahStringDedupRoots _dedup_roots;
|
||||||
ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator> _code_roots;
|
ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator> _code_roots;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase);
|
ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase);
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "gc/shenandoah/shenandoahTimingTracker.hpp"
|
#include "gc/shenandoah/shenandoahTimingTracker.hpp"
|
||||||
#include "gc/shenandoah/shenandoahUtils.hpp"
|
#include "gc/shenandoah/shenandoahUtils.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "runtime/safepoint.hpp"
|
||||||
|
|
||||||
template <bool CONCURRENT>
|
template <bool CONCURRENT>
|
||||||
ShenandoahJNIHandleRoots<CONCURRENT>::ShenandoahJNIHandleRoots() :
|
ShenandoahJNIHandleRoots<CONCURRENT>::ShenandoahJNIHandleRoots() :
|
||||||
|
@ -54,6 +55,27 @@ void ShenandoahWeakRoots::oops_do(IsAlive* is_alive, KeepAlive* keep_alive, uint
|
||||||
_task.work<IsAlive, KeepAlive>(worker_id, is_alive, keep_alive);
|
_task.work<IsAlive, KeepAlive>(worker_id, is_alive, keep_alive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <bool SINGLE_THREADED>
|
||||||
|
ShenandoahClassLoaderDataRoots<SINGLE_THREADED>::ShenandoahClassLoaderDataRoots() {
|
||||||
|
if (!SINGLE_THREADED) {
|
||||||
|
ClassLoaderDataGraph::clear_claimed_marks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool SINGLE_THREADED>
|
||||||
|
void ShenandoahClassLoaderDataRoots<SINGLE_THREADED>::clds_do(CLDClosure* strong_clds, CLDClosure* weak_clds, uint worker_id) {
|
||||||
|
if (SINGLE_THREADED) {
|
||||||
|
assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
|
||||||
|
assert(Thread::current()->is_VM_thread(), "Single threaded CLDG iteration can only be done by VM thread");
|
||||||
|
|
||||||
|
ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds);
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename ITR>
|
template <typename ITR>
|
||||||
ShenandoahCodeCacheRoots<ITR>::ShenandoahCodeCacheRoots() {
|
ShenandoahCodeCacheRoots<ITR>::ShenandoahCodeCacheRoots() {
|
||||||
nmethod::oops_do_marking_prologue();
|
nmethod::oops_do_marking_prologue();
|
||||||
|
@ -130,33 +152,6 @@ void ShenandoahRootScanner<ITR>::roots_do(uint worker_id, OopClosure* oops, CLDC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ITR>
|
|
||||||
void ShenandoahRootScanner<ITR>::roots_do_unchecked(OopClosure* oops) {
|
|
||||||
CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong);
|
|
||||||
MarkingCodeBlobClosure code(oops, !CodeBlobToOopClosure::FixRelocations);
|
|
||||||
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, &code, NULL);
|
|
||||||
ResourceMark rm;
|
|
||||||
|
|
||||||
_serial_roots.oops_do(oops, 0);
|
|
||||||
_jni_roots.oops_do(oops, 0);
|
|
||||||
_cld_roots.clds_do(&clds, &clds, 0);
|
|
||||||
_thread_roots.threads_do(&tc_cl, 0);
|
|
||||||
_code_roots.code_blobs_do(&code, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ITR>
|
|
||||||
void ShenandoahRootScanner<ITR>::strong_roots_do_unchecked(OopClosure* oops) {
|
|
||||||
CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong);
|
|
||||||
MarkingCodeBlobClosure code(oops, !CodeBlobToOopClosure::FixRelocations);
|
|
||||||
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, &code, NULL);
|
|
||||||
ResourceMark rm;
|
|
||||||
|
|
||||||
_serial_roots.oops_do(oops, 0);
|
|
||||||
_jni_roots.oops_do(oops, 0);
|
|
||||||
_cld_roots.clds_do(&clds, NULL, 0);
|
|
||||||
_thread_roots.threads_do(&tc_cl, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ITR>
|
template <typename ITR>
|
||||||
void ShenandoahRootScanner<ITR>::strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc) {
|
void ShenandoahRootScanner<ITR>::strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc) {
|
||||||
assert(ShenandoahHeap::heap()->unload_classes(), "Should be used during class unloading");
|
assert(ShenandoahHeap::heap()->unload_classes(), "Should be used during class unloading");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue