8226413: Shenandoah: Separate root scanner for SH::object_iterate()
authorzgu
Thu, 20 Jun 2019 10:12:31 -0400
changeset 55444 6a7d6b6bbd78
parent 55443 99b604ec1af6
child 55445 a7b9d6d4940e
8226413: Shenandoah: Separate root scanner for SH::object_iterate() Reviewed-by: rkennke
src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp
src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp
src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp
--- 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);