8226413: Shenandoah: Separate root scanner for SH::object_iterate()
Reviewed-by: rkennke
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Thu Jun 20 07:13:06 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Thu Jun 20 10:12:31 2019 -0400
@@ -1279,14 +1279,14 @@
Stack<oop,mtGC> oop_stack;
- // First, we process all GC roots. This populates the work stack with initial objects.
- ShenandoahAllRootScanner rp(1, ShenandoahPhaseTimings::_num_phases);
+ // First, we process GC roots according to current GC cycle. This populates the work stack with initial objects.
+ ShenandoahHeapIterationRootScanner rp;
ObjectIterateScanRootClosure oops(&_aux_bit_map, &oop_stack);
if (unload_classes()) {
- rp.strong_roots_do_unchecked(&oops);
+ rp.strong_roots_do(&oops);
} else {
- rp.roots_do_unchecked(&oops);
+ rp.roots_do(&oops);
}
// Work through the oop stack to traverse heap.
@@ -1587,7 +1587,7 @@
class ShenandoahConcurrentRootsEvacUpdateTask : public AbstractGangTask {
private:
- ShenandoahJNIHandleRoots<true /*concurrent*/> _jni_roots;
+ ShenandoahJNIHandleRoots<true /*concurrent*/> _jni_roots;
public:
ShenandoahConcurrentRootsEvacUpdateTask() :
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp Thu Jun 20 07:13:06 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp Thu Jun 20 10:12:31 2019 -0400
@@ -122,16 +122,6 @@
}
}
-ShenandoahClassLoaderDataRoots::ShenandoahClassLoaderDataRoots() {
- ClassLoaderDataGraph::clear_claimed_marks();
-}
-
-void ShenandoahClassLoaderDataRoots::clds_do(CLDClosure* strong_clds, CLDClosure* weak_clds, uint worker_id) {
- ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
- ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id);
- ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds);
-}
-
ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase) :
_heap(ShenandoahHeap::heap()),
_phase(phase) {
@@ -198,3 +188,37 @@
_weak_roots.oops_do<AlwaysTrueClosure, OopClosure>(&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);
+ }
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp Thu Jun 20 07:13:06 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp Thu Jun 20 10:12:31 2019 -0400
@@ -114,6 +114,7 @@
void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id);
};
+template <bool SINGLE_THREADED>
class ShenandoahClassLoaderDataRoots {
public:
ShenandoahClassLoaderDataRoots();
@@ -135,11 +136,11 @@
template <typename ITR>
class ShenandoahRootScanner : public ShenandoahRootProcessor {
private:
- ShenandoahSerialRoots _serial_roots;
- ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
- ShenandoahClassLoaderDataRoots _cld_roots;
- ShenandoahThreadRoots _thread_roots;
- ShenandoahCodeCacheRoots<ITR> _code_roots;
+ ShenandoahSerialRoots _serial_roots;
+ ShenandoahThreadRoots _thread_roots;
+ ShenandoahCodeCacheRoots<ITR> _code_roots;
+ ShenandoahJNIHandleRoots<false /*concurrent*/ > _jni_roots;
+ ShenandoahClassLoaderDataRoots<false /*single threaded*/> _cld_roots;
public:
ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
@@ -152,20 +153,34 @@
// 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);
- // For heap object iteration
- void roots_do_unchecked(OopClosure* cl);
- void strong_roots_do_unchecked(OopClosure* cl);
};
typedef ShenandoahRootScanner<ShenandoahAllCodeRootsIterator> ShenandoahAllRootScanner;
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
class ShenandoahRootEvacuator : public ShenandoahRootProcessor {
private:
ShenandoahSerialRoots _serial_roots;
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
- ShenandoahClassLoaderDataRoots _cld_roots;
+ ShenandoahClassLoaderDataRoots<false /*single threaded*/> _cld_roots;
ShenandoahThreadRoots _thread_roots;
ShenandoahWeakRoots _weak_roots;
ShenandoahStringDedupRoots _dedup_roots;
@@ -183,7 +198,7 @@
private:
ShenandoahSerialRoots _serial_roots;
ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
- ShenandoahClassLoaderDataRoots _cld_roots;
+ ShenandoahClassLoaderDataRoots<false /*single threaded*/> _cld_roots;
ShenandoahThreadRoots _thread_roots;
ShenandoahWeakRoots _weak_roots;
ShenandoahStringDedupRoots _dedup_roots;
@@ -200,13 +215,13 @@
// Adjuster all roots at a safepoint during full gc
class ShenandoahRootAdjuster : public ShenandoahRootProcessor {
private:
- ShenandoahSerialRoots _serial_roots;
- ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
- ShenandoahClassLoaderDataRoots _cld_roots;
- ShenandoahThreadRoots _thread_roots;
- ShenandoahWeakRoots _weak_roots;
- ShenandoahStringDedupRoots _dedup_roots;
- ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator> _code_roots;
+ ShenandoahSerialRoots _serial_roots;
+ ShenandoahJNIHandleRoots<false /*concurrent*/> _jni_roots;
+ ShenandoahClassLoaderDataRoots<false /*single threaded*/> _cld_roots;
+ ShenandoahThreadRoots _thread_roots;
+ ShenandoahWeakRoots _weak_roots;
+ ShenandoahStringDedupRoots _dedup_roots;
+ ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator> _code_roots;
public:
ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase);
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp Thu Jun 20 07:13:06 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp Thu Jun 20 10:12:31 2019 -0400
@@ -31,6 +31,7 @@
#include "gc/shenandoah/shenandoahTimingTracker.hpp"
#include "gc/shenandoah/shenandoahUtils.hpp"
#include "memory/resourceArea.hpp"
+#include "runtime/safepoint.hpp"
template <bool CONCURRENT>
ShenandoahJNIHandleRoots<CONCURRENT>::ShenandoahJNIHandleRoots() :
@@ -54,6 +55,27 @@
_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>
ShenandoahCodeCacheRoots<ITR>::ShenandoahCodeCacheRoots() {
nmethod::oops_do_marking_prologue();
@@ -131,33 +153,6 @@
}
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>
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");
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc);