src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp
changeset 54940 2d90a0988c95
parent 54924 ba1eccda5450
child 54976 b1f070f4a4ae
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp	Thu May 16 12:14:37 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp	Mon May 20 09:42:37 2019 -0400
@@ -24,6 +24,7 @@
 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP
 #define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP
 
+#include "gc/shenandoah/shenandoahHeuristics.hpp"
 #include "gc/shenandoah/shenandoahRootProcessor.hpp"
 #include "gc/shenandoah/shenandoahTimingTracker.hpp"
 
@@ -49,6 +50,74 @@
   nmethod::oops_do_marking_epilogue();
 }
 
+class ShenandoahParallelOopsDoThreadClosure : public ThreadClosure {
+private:
+  OopClosure* _f;
+  CodeBlobClosure* _cf;
+  ThreadClosure* _thread_cl;
+public:
+  ShenandoahParallelOopsDoThreadClosure(OopClosure* f, CodeBlobClosure* cf, ThreadClosure* thread_cl) :
+    _f(f), _cf(cf), _thread_cl(thread_cl) {}
+
+  void do_thread(Thread* t) {
+    if (_thread_cl != NULL) {
+      _thread_cl->do_thread(t);
+    }
+    t->oops_do(_f, _cf);
+  }
+};
+
+template <typename ITR>
+ShenandoahRootScanner<ITR>::ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
+  ShenandoahRootProcessor(phase),
+  _thread_roots(n_workers > 1) {
+}
+
+template <typename ITR>
+void ShenandoahRootScanner<ITR>::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);
+}
+
+template <typename ITR>
+void ShenandoahRootScanner<ITR>::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);
+}
+
+template <typename ITR>
+void ShenandoahRootScanner<ITR>::roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure *tc) {
+  assert(!ShenandoahHeap::heap()->unload_classes() ||
+          ShenandoahHeap::heap()->heuristics()->can_do_traversal_gc(),
+          "No class unloading or traversal GC");
+  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);
+  }
+}
+
+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);
+  ResourceMark rm;
+
+  _serial_roots.oops_do(oops, worker_id);
+  _cld_roots.clds_do(clds, NULL, worker_id);
+  _thread_roots.threads_do(&tc_cl, worker_id);
+}
+
 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);