8223774: Shenandoah: Refactor ShenandoahRootProcessor and family
authorzgu
Fri, 17 May 2019 09:52:35 -0400
changeset 54924 ba1eccda5450
parent 54923 23837d614c17
child 54925 3205f4c40716
8223774: Shenandoah: Refactor ShenandoahRootProcessor and family Reviewed-by: shade, rkennke
src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp
src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp
src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp
src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp
src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp
src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp
--- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp	Fri May 17 12:33:37 2019 +0200
+++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp	Fri May 17 09:52:35 2019 -0400
@@ -81,10 +81,10 @@
 template<UpdateRefsMode UPDATE_REFS>
 class ShenandoahInitMarkRootsTask : public AbstractGangTask {
 private:
-  ShenandoahRootProcessor* _rp;
+  ShenandoahRootScanner* _rp;
   bool _process_refs;
 public:
-  ShenandoahInitMarkRootsTask(ShenandoahRootProcessor* rp, bool process_refs) :
+  ShenandoahInitMarkRootsTask(ShenandoahRootScanner* rp, bool process_refs) :
     AbstractGangTask("Shenandoah init mark roots task"),
     _rp(rp),
     _process_refs(process_refs) {
@@ -115,45 +115,21 @@
     //      cache, because there could be the case of embedded class/oop in the generated code,
     //      which we will never visit during mark. Without code cache invalidation, as in (a),
     //      we risk executing that code cache blob, and crashing.
-    //   c. 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.
-
-    CLDToOopClosure clds_cl(oops, ClassLoaderData::_claim_strong);
-    MarkingCodeBlobClosure blobs_cl(oops, ! CodeBlobToOopClosure::FixRelocations);
-
-    ResourceMark m;
     if (heap->unload_classes()) {
-      _rp->process_strong_roots(oops, &clds_cl, &blobs_cl, NULL, worker_id);
+      _rp->strong_roots_do(worker_id, oops);
     } else {
-      if (ShenandoahConcurrentScanCodeRoots) {
-        CodeBlobClosure* code_blobs = NULL;
-#ifdef ASSERT
-        ShenandoahAssertToSpaceClosure assert_to_space_oops;
-        CodeBlobToOopClosure assert_to_space(&assert_to_space_oops, !CodeBlobToOopClosure::FixRelocations);
-        // If conc code cache evac is disabled, code cache should have only to-space ptrs.
-        // Otherwise, it should have to-space ptrs only if mark does not update refs.
-        if (!heap->has_forwarded_objects()) {
-          code_blobs = &assert_to_space;
-        }
-#endif
-        _rp->process_all_roots(oops, &clds_cl, code_blobs, NULL, worker_id);
-      } else {
-        _rp->process_all_roots(oops, &clds_cl, &blobs_cl, NULL, worker_id);
-      }
+      _rp->roots_do(worker_id, oops);
     }
   }
 };
 
 class ShenandoahUpdateRootsTask : public AbstractGangTask {
 private:
-  ShenandoahRootProcessor* _rp;
-  const bool _update_code_cache;
+  ShenandoahRootUpdater*  _root_updater;
 public:
-  ShenandoahUpdateRootsTask(ShenandoahRootProcessor* rp, bool update_code_cache) :
+  ShenandoahUpdateRootsTask(ShenandoahRootUpdater* root_updater) :
     AbstractGangTask("Shenandoah update roots task"),
-    _rp(rp),
-    _update_code_cache(update_code_cache) {
+    _root_updater(root_updater) {
   }
 
   void work(uint worker_id) {
@@ -162,22 +138,8 @@
 
     ShenandoahHeap* heap = ShenandoahHeap::heap();
     ShenandoahUpdateRefsClosure cl;
-    CLDToOopClosure cldCl(&cl, ClassLoaderData::_claim_strong);
-
-    CodeBlobClosure* code_blobs;
-    CodeBlobToOopClosure update_blobs(&cl, CodeBlobToOopClosure::FixRelocations);
-#ifdef ASSERT
-    ShenandoahAssertToSpaceClosure assert_to_space_oops;
-    CodeBlobToOopClosure assert_to_space(&assert_to_space_oops, !CodeBlobToOopClosure::FixRelocations);
-#endif
-    if (_update_code_cache) {
-      code_blobs = &update_blobs;
-    } else {
-      code_blobs =
-        DEBUG_ONLY(&assert_to_space)
-        NOT_DEBUG(NULL);
-    }
-    _rp->update_all_roots<AlwaysTrueClosure>(&cl, &cldCl, code_blobs, NULL, worker_id);
+    AlwaysTrueClosure always_true;
+    _root_updater->roots_do<AlwaysTrueClosure, ShenandoahUpdateRefsClosure>(worker_id, &always_true, &cl);
   }
 };
 
@@ -289,7 +251,7 @@
 
   assert(nworkers <= task_queues()->size(), "Just check");
 
-  ShenandoahRootProcessor root_proc(heap, nworkers, root_phase);
+  ShenandoahRootScanner root_proc(nworkers, root_phase);
   TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
   task_queues()->reserve(nworkers);
 
@@ -333,8 +295,8 @@
 
   uint nworkers = _heap->workers()->active_workers();
 
-  ShenandoahRootProcessor root_proc(_heap, nworkers, root_phase);
-  ShenandoahUpdateRootsTask update_roots(&root_proc, update_code_cache);
+  ShenandoahRootUpdater root_updater(nworkers, root_phase, update_code_cache);
+  ShenandoahUpdateRootsTask update_roots(&root_updater);
   _heap->workers()->run_task(&update_roots);
 
 #if defined(COMPILER2) || INCLUDE_JVMCI
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Fri May 17 12:33:37 2019 +0200
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Fri May 17 09:52:35 2019 -0400
@@ -52,7 +52,7 @@
 #include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
 #include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
 #include "gc/shenandoah/shenandoahPacer.inline.hpp"
-#include "gc/shenandoah/shenandoahRootProcessor.hpp"
+#include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
 #include "gc/shenandoah/shenandoahStringDedup.hpp"
 #include "gc/shenandoah/shenandoahTaskqueue.hpp"
 #include "gc/shenandoah/shenandoahUtils.hpp"
@@ -1111,7 +1111,7 @@
     ShenandoahEvacOOMScope oom_evac_scope;
     ShenandoahEvacuateUpdateRootsClosure cl;
     MarkingCodeBlobClosure blobsCl(&cl, CodeBlobToOopClosure::FixRelocations);
-    _rp->process_evacuate_roots(&cl, &blobsCl, worker_id);
+    _rp->roots_do(worker_id, &cl);
   }
 };
 
@@ -1122,7 +1122,7 @@
   assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Only iterate roots while world is stopped");
 
   {
-    ShenandoahRootEvacuator rp(this, workers()->active_workers(), ShenandoahPhaseTimings::init_evac);
+    ShenandoahRootEvacuator rp(workers()->active_workers(), ShenandoahPhaseTimings::init_evac);
     ShenandoahEvacuateUpdateRootsTask roots_task(&rp);
     workers()->run_task(&roots_task);
   }
@@ -1326,11 +1326,9 @@
   Stack<oop,mtGC> oop_stack;
 
   // First, we process all GC roots. This populates the work stack with initial objects.
-  ShenandoahRootProcessor rp(this, 1, ShenandoahPhaseTimings::_num_phases);
+  ShenandoahRootScanner rp(1, ShenandoahPhaseTimings::_num_phases);
   ObjectIterateScanRootClosure oops(&_aux_bit_map, &oop_stack);
-  CLDToOopClosure clds(&oops, ClassLoaderData::_claim_none);
-  CodeBlobToOopClosure blobs(&oops, false);
-  rp.process_all_roots(&oops, &clds, &blobs, NULL, 0);
+  rp.roots_do(0, &oops);
 
   // Work through the oop stack to traverse heap.
   while (! oop_stack.is_empty()) {
--- a/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp	Fri May 17 12:33:37 2019 +0200
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp	Fri May 17 09:52:35 2019 -0400
@@ -561,22 +561,16 @@
 
 class ShenandoahAdjustRootPointersTask : public AbstractGangTask {
 private:
-  ShenandoahRootProcessor* _rp;
+  ShenandoahRootAdjuster* _rp;
 
 public:
-  ShenandoahAdjustRootPointersTask(ShenandoahRootProcessor* rp) :
+  ShenandoahAdjustRootPointersTask(ShenandoahRootAdjuster* rp) :
     AbstractGangTask("Shenandoah Adjust Root Pointers Task"),
     _rp(rp) {}
 
   void work(uint worker_id) {
     ShenandoahAdjustPointersClosure cl;
-    CLDToOopClosure adjust_cld_closure(&cl, ClassLoaderData::_claim_strong);
-    MarkingCodeBlobClosure adjust_code_closure(&cl,
-                                             CodeBlobToOopClosure::FixRelocations);
-
-    _rp->update_all_roots<AlwaysTrueClosure>(&cl,
-                                             &adjust_cld_closure,
-                                             &adjust_code_closure, NULL, worker_id);
+    _rp->roots_do(worker_id, &cl);
   }
 };
 
@@ -592,7 +586,7 @@
 #if COMPILER2_OR_JVMCI
     DerivedPointerTable::clear();
 #endif
-    ShenandoahRootProcessor rp(heap, nworkers, ShenandoahPhaseTimings::full_gc_roots);
+    ShenandoahRootAdjuster rp(nworkers, ShenandoahPhaseTimings::full_gc_roots);
     ShenandoahAdjustRootPointersTask task(&rp);
     workers->run_task(&task);
 #if COMPILER2_OR_JVMCI
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Fri May 17 12:33:37 2019 +0200
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Fri May 17 09:52:35 2019 -0400
@@ -28,8 +28,9 @@
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
 #include "gc/shenandoah/shenandoahClosures.inline.hpp"
-#include "gc/shenandoah/shenandoahRootProcessor.hpp"
+#include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
 #include "gc/shenandoah/shenandoahHeap.hpp"
+#include "gc/shenandoah/shenandoahHeuristics.hpp"
 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
 #include "gc/shenandoah/shenandoahStringDedup.hpp"
 #include "gc/shenandoah/shenandoahTimingTracker.hpp"
@@ -43,67 +44,95 @@
 #include "runtime/thread.hpp"
 #include "services/management.hpp"
 
-ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahHeap* heap, uint n_workers,
-                                                 ShenandoahPhaseTimings::Phase phase) :
-  _process_strong_tasks(new SubTasksDone(SHENANDOAH_RP_PS_NumElements)),
-  _srs(n_workers),
-  _phase(phase),
-  _coderoots_all_iterator(ShenandoahCodeRoots::iterator()),
-  _weak_processor_timings(n_workers),
-  _weak_processor_task(&_weak_processor_timings, n_workers),
-  _processed_weak_roots(false) {
-  heap->phase_timings()->record_workers_start(_phase);
+ShenandoahSerialRoot::ShenandoahSerialRoot(ShenandoahSerialRoot::OopsDo oops_do, ShenandoahPhaseTimings::GCParPhases phase) :
+  _claimed(false), _oops_do(oops_do), _phase(phase) {
+}
+
+void ShenandoahSerialRoot::oops_do(OopClosure* cl, uint worker_id) {
+  if (!_claimed && Atomic::cmpxchg(true, &_claimed, false) == false) {
+    ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
+    ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id);
+    _oops_do(cl);
+  }
+}
+
+ShenandoahSerialRoots::ShenandoahSerialRoots() :
+  _universe_root(&Universe::oops_do, ShenandoahPhaseTimings::UniverseRoots),
+  _object_synchronizer_root(&ObjectSynchronizer::oops_do, ShenandoahPhaseTimings::ObjectSynchronizerRoots),
+  _management_root(&Management::oops_do, ShenandoahPhaseTimings::ManagementRoots),
+  _system_dictionary_root(&SystemDictionary::oops_do, ShenandoahPhaseTimings::SystemDictionaryRoots),
+  _jvmti_root(&JvmtiExport::oops_do, ShenandoahPhaseTimings::JVMTIRoots),
+  _jni_handle_root(&JNIHandles::oops_do, ShenandoahPhaseTimings::JNIRoots) {
+}
+
+void ShenandoahSerialRoots::oops_do(OopClosure* cl, uint worker_id) {
+  _universe_root.oops_do(cl, worker_id);
+  _object_synchronizer_root.oops_do(cl, worker_id);
+  _management_root.oops_do(cl, worker_id);
+  _system_dictionary_root.oops_do(cl, worker_id);
+  _jvmti_root.oops_do(cl, worker_id);
+  _jni_handle_root.oops_do(cl, worker_id);
+}
 
+ShenandoahThreadRoots::ShenandoahThreadRoots(bool is_par) : _is_par(is_par) {
+  Threads::change_thread_claim_token();
+}
+
+void ShenandoahThreadRoots::oops_do(OopClosure* oops_cl, CodeBlobClosure* code_cl, uint worker_id) {
+  ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
+  ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id);
+  ResourceMark rm;
+  Threads::possibly_parallel_oops_do(_is_par, oops_cl, code_cl);
+}
+
+void ShenandoahThreadRoots::threads_do(ThreadClosure* tc, uint worker_id) {
+  ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
+  ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id);
+  ResourceMark rm;
+  Threads::possibly_parallel_threads_do(_is_par, tc);
+}
+
+ShenandoahThreadRoots::~ShenandoahThreadRoots() {
+  Threads::assert_all_threads_claimed();
+}
+
+ShenandoahWeakRoots::ShenandoahWeakRoots(uint n_workers) :
+  _process_timings(n_workers),
+  _task(&_process_timings, n_workers) {
+}
+
+ShenandoahWeakRoots::~ShenandoahWeakRoots() {
+  ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
+  ShenandoahTimingConverter::weak_processing_timing_to_shenandoah_timing(&_process_timings,
+                                                                         worker_times);
+}
+
+ShenandoahStringDedupRoots::ShenandoahStringDedupRoots() {
   if (ShenandoahStringDedup::is_enabled()) {
     StringDedup::gc_prologue(false);
   }
 }
 
-ShenandoahRootProcessor::~ShenandoahRootProcessor() {
-  delete _process_strong_tasks;
+ShenandoahStringDedupRoots::~ShenandoahStringDedupRoots() {
   if (ShenandoahStringDedup::is_enabled()) {
     StringDedup::gc_epilogue();
   }
+}
 
-  if (_processed_weak_roots) {
-    assert(_weak_processor_timings.max_threads() == n_workers(), "Must match");
-    ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
-    ShenandoahTimingConverter::weak_processing_timing_to_shenandoah_timing(&_weak_processor_timings,
-                                                                           worker_times);
+void ShenandoahStringDedupRoots::oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id) {
+  if (ShenandoahStringDedup::is_enabled()) {
+    ShenandoahStringDedup::parallel_oops_do(is_alive, keep_alive, worker_id);
   }
-
-  ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase);
 }
 
-void ShenandoahRootProcessor::process_strong_roots(OopClosure* oops,
-                                                   CLDClosure* clds,
-                                                   CodeBlobClosure* blobs,
-                                                   ThreadClosure* thread_cl,
-                                                   uint worker_id) {
-
-  process_java_roots(oops, clds, NULL, blobs, thread_cl, worker_id);
-  process_vm_roots(oops, worker_id);
-
-  _process_strong_tasks->all_tasks_completed(n_workers());
+ShenandoahClassLoaderDataRoots::ShenandoahClassLoaderDataRoots() {
+  ClassLoaderDataGraph::clear_claimed_marks();
 }
 
-void ShenandoahRootProcessor::process_all_roots(OopClosure* oops,
-                                                CLDClosure* clds,
-                                                CodeBlobClosure* blobs,
-                                                ThreadClosure* thread_cl,
-                                                uint worker_id) {
-
+void ShenandoahClassLoaderDataRoots::clds_do(CLDClosure* strong_clds, CLDClosure* weak_clds, uint worker_id) {
   ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
-  process_java_roots(oops, clds, clds, blobs, thread_cl, worker_id);
-  process_vm_roots(oops, worker_id);
-
-  if (blobs != NULL) {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id);
-    _coderoots_all_iterator.possibly_parallel_blobs_do(blobs);
-  }
-
-  _process_strong_tasks->all_tasks_completed(n_workers());
-
+  ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id);
+  ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds);
 }
 
 class ShenandoahParallelOopsDoThreadClosure : public ThreadClosure {
@@ -123,168 +152,110 @@
   }
 };
 
-void ShenandoahRootProcessor::process_java_roots(OopClosure* strong_roots,
-                                                 CLDClosure* strong_clds,
-                                                 CLDClosure* weak_clds,
-                                                 CodeBlobClosure* strong_code,
-                                                 ThreadClosure* thread_cl,
-                                                 uint worker_id)
-{
-  ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
-  // Iterating over the CLDG and the Threads are done early to allow us to
-  // first process the strong CLDs and nmethods and then, after a barrier,
-  // let the thread process the weak CLDs and nmethods.
-  {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id);
-    _cld_iterator.root_cld_do(strong_clds, weak_clds);
-  }
+ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase) :
+  _heap(ShenandoahHeap::heap()),
+  _phase(phase) {
+  assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint");
+  _heap->phase_timings()->record_workers_start(_phase);
+}
 
-  {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id);
-    bool is_par = n_workers() > 1;
-    ResourceMark rm;
-    ShenandoahParallelOopsDoThreadClosure cl(strong_roots, strong_code, thread_cl);
-    Threads::possibly_parallel_threads_do(is_par, &cl);
-  }
+ShenandoahRootProcessor::~ShenandoahRootProcessor() {
+  assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint");
+  _heap->phase_timings()->record_workers_end(_phase);
+}
+
+ShenandoahRootScanner::ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
+  ShenandoahRootProcessor(phase),
+  _thread_roots(n_workers > 1) {
 }
 
-void ShenandoahRootProcessor::process_vm_roots(OopClosure* strong_roots,
-                                               uint worker_id) {
-  ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
-  if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_Universe_oops_do)) {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::UniverseRoots, worker_id);
-    Universe::oops_do(strong_roots);
-  }
+void ShenandoahRootScanner::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);
+}
 
-  if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_JNIHandles_oops_do)) {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JNIRoots, worker_id);
-    JNIHandles::oops_do(strong_roots);
-  }
-  if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_Management_oops_do)) {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ManagementRoots, worker_id);
-    Management::oops_do(strong_roots);
-  }
-  if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_jvmti_oops_do)) {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JVMTIRoots, worker_id);
-    JvmtiExport::oops_do(strong_roots);
-  }
-  if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_SystemDictionary_oops_do)) {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::SystemDictionaryRoots, worker_id);
-    SystemDictionary::oops_do(strong_roots);
-  }
-
-  {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ObjectSynchronizerRoots, worker_id);
-    if (_process_strong_tasks->try_claim_task(SHENANDOAH_RP_PS_ObjectSynchronizer_oops_do)) {
-      ObjectSynchronizer::oops_do(strong_roots);
-    }
-  }
+void ShenandoahRootScanner::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);
 }
 
-uint ShenandoahRootProcessor::n_workers() const {
-  return _srs.n_threads();
-}
+void ShenandoahRootScanner::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;
 
-ShenandoahRootEvacuator::ShenandoahRootEvacuator(ShenandoahHeap* heap, uint n_workers, ShenandoahPhaseTimings::Phase phase) :
-  _evacuation_tasks(new SubTasksDone(SHENANDOAH_EVAC_NumElements)),
-  _srs(n_workers),
-  _phase(phase),
-  _coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator()),
-  _weak_processor_timings(n_workers),
-  _weak_processor_task(&_weak_processor_timings, n_workers) {
-  heap->phase_timings()->record_workers_start(_phase);
-  if (ShenandoahStringDedup::is_enabled()) {
-    StringDedup::gc_prologue(false);
+  _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);
   }
 }
 
-ShenandoahRootEvacuator::~ShenandoahRootEvacuator() {
-  delete _evacuation_tasks;
-  if (ShenandoahStringDedup::is_enabled()) {
-    StringDedup::gc_epilogue();
-  }
+void ShenandoahRootScanner::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;
 
-  ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
-  assert(_weak_processor_timings.max_threads() == n_workers(), "Must match");
-  ShenandoahTimingConverter::weak_processing_timing_to_shenandoah_timing(&_weak_processor_timings,
-                                                                         worker_times);
-
-  ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase);
+  _serial_roots.oops_do(oops, worker_id);
+  _cld_roots.clds_do(clds, NULL, worker_id);
+  _thread_roots.threads_do(&tc_cl, worker_id);
 }
 
-void ShenandoahRootEvacuator::process_evacuate_roots(OopClosure* oops,
-                                                     CodeBlobClosure* blobs,
-                                                     uint worker_id) {
+ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
+  ShenandoahRootProcessor(phase),
+  _thread_roots(n_workers > 1),
+  _weak_roots(n_workers) {
+}
+
+void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) {
+  MarkingCodeBlobClosure blobsCl(oops, CodeBlobToOopClosure::FixRelocations);
+  CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong);
+  CLDToOopClosure* weak_clds = ShenandoahHeap::heap()->unload_classes() ? NULL : &clds;
 
   AlwaysTrueClosure always_true;
-  ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
-  {
-    bool is_par = n_workers() > 1;
-    ResourceMark rm;
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id);
-    Threads::possibly_parallel_oops_do(is_par, oops, NULL);
-  }
 
-  {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id);
-    CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong);
-    _cld_iterator.root_cld_do(&clds, &clds);
-  }
+  _serial_roots.oops_do(oops, worker_id);
 
-  if (blobs != NULL) {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id);
-    _coderoots_cset_iterator.possibly_parallel_blobs_do(blobs);
-  }
-
-  if (ShenandoahStringDedup::is_enabled()) {
-    ShenandoahStringDedup::parallel_oops_do(&always_true, oops, worker_id);
-  }
-
-  if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_Universe_oops_do)) {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::UniverseRoots, worker_id);
-    Universe::oops_do(oops);
-  }
+  _thread_roots.oops_do(oops, NULL, worker_id);
+  _cld_roots.clds_do(&clds, &clds, worker_id);
+  _code_roots.code_blobs_do(&blobsCl, worker_id);
 
-  if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_Management_oops_do)) {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ManagementRoots, worker_id);
-    Management::oops_do(oops);
-  }
-
-  if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_jvmti_oops_do)) {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JVMTIRoots, worker_id);
-    JvmtiExport::oops_do(oops);
-    ShenandoahForwardedIsAliveClosure is_alive;
-    JvmtiExport::weak_oops_do(&is_alive, oops);
-  }
+  _weak_roots.oops_do<AlwaysTrueClosure, OopClosure>(&always_true, oops, worker_id);
+  _dedup_roots.oops_do(&always_true, oops, worker_id);
+}
 
-  if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_JNIHandles_oops_do)) {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JNIRoots, worker_id);
-    JNIHandles::oops_do(oops);
-  }
-
-  if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_SystemDictionary_oops_do)) {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::SystemDictionaryRoots, worker_id);
-    SystemDictionary::oops_do(oops);
-  }
-
-  if (_evacuation_tasks->try_claim_task(SHENANDOAH_EVAC_ObjectSynchronizer_oops_do)) {
-    ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ObjectSynchronizerRoots, worker_id);
-    ObjectSynchronizer::oops_do(oops);
-  }
-
-  _weak_processor_task.work<AlwaysTrueClosure, OopClosure>(worker_id, &always_true, oops);
+ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool update_code_cache) :
+  ShenandoahRootProcessor(phase),
+  _thread_roots(n_workers > 1),
+  _weak_roots(n_workers),
+  _update_code_cache(update_code_cache) {
 }
 
-uint ShenandoahRootEvacuator::n_workers() const {
-  return _srs.n_threads();
+ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
+  ShenandoahRootProcessor(phase),
+  _thread_roots(n_workers > 1),
+  _weak_roots(n_workers) {
+  assert(ShenandoahHeap::heap()->is_full_gc_in_progress(), "Full GC only");
 }
 
-// Implemenation of ParallelCLDRootIterator
-ParallelCLDRootIterator::ParallelCLDRootIterator() {
-  assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint");
-  ClassLoaderDataGraph::clear_claimed_marks();
+void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) {
+  CodeBlobToOopClosure adjust_code_closure(oops, CodeBlobToOopClosure::FixRelocations);
+  CLDToOopClosure adjust_cld_closure(oops, ClassLoaderData::_claim_strong);
+  AlwaysTrueClosure always_true;
+
+  _serial_roots.oops_do(oops, worker_id);
+
+  _thread_roots.oops_do(oops, NULL, worker_id);
+  _cld_roots.clds_do(&adjust_cld_closure, NULL, worker_id);
+  _code_roots.code_blobs_do(&adjust_code_closure, worker_id);
+
+  _weak_roots.oops_do<AlwaysTrueClosure, OopClosure>(&always_true, oops, worker_id);
+  _dedup_roots.oops_do(&always_true, oops, worker_id);
 }
-
-void ParallelCLDRootIterator::root_cld_do(CLDClosure* strong, CLDClosure* weak) {
-    ClassLoaderDataGraph::roots_cld_do(strong, weak);
-}
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp	Fri May 17 12:33:37 2019 +0200
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp	Fri May 17 09:52:35 2019 -0400
@@ -36,110 +36,160 @@
 #include "memory/allocation.hpp"
 #include "memory/iterator.hpp"
 
-class ParallelCLDRootIterator {
+class ShenandoahSerialRoot {
+public:
+  typedef void (*OopsDo)(OopClosure*);
+private:
+  volatile bool                             _claimed;
+  const OopsDo                              _oops_do;
+  const ShenandoahPhaseTimings::GCParPhases _phase;
+
 public:
-  ParallelCLDRootIterator();
-  void root_cld_do(CLDClosure* strong, CLDClosure* weak);
+  ShenandoahSerialRoot(OopsDo oops_do, ShenandoahPhaseTimings::GCParPhases);
+  void oops_do(OopClosure* cl, uint worker_id);
+};
+
+class ShenandoahSerialRoots {
+private:
+  ShenandoahSerialRoot  _universe_root;
+  ShenandoahSerialRoot  _object_synchronizer_root;
+  ShenandoahSerialRoot  _management_root;
+  ShenandoahSerialRoot  _system_dictionary_root;
+  ShenandoahSerialRoot  _jvmti_root;
+  ShenandoahSerialRoot  _jni_handle_root;
+public:
+  ShenandoahSerialRoots();
+  void oops_do(OopClosure* cl, uint worker_id);
+};
+
+class ShenandoahThreadRoots {
+private:
+  const bool _is_par;
+public:
+  ShenandoahThreadRoots(bool is_par);
+  ~ShenandoahThreadRoots();
+
+  void oops_do(OopClosure* oops_cl, CodeBlobClosure* code_cl, uint worker_id);
+  void threads_do(ThreadClosure* tc, uint worker_id);
 };
 
-enum Shenandoah_process_roots_tasks {
-  SHENANDOAH_RP_PS_Universe_oops_do,
-  SHENANDOAH_RP_PS_JNIHandles_oops_do,
-  SHENANDOAH_RP_PS_ObjectSynchronizer_oops_do,
-  SHENANDOAH_RP_PS_Management_oops_do,
-  SHENANDOAH_RP_PS_SystemDictionary_oops_do,
-  SHENANDOAH_RP_PS_jvmti_oops_do,
-  // Leave this one last.
-  SHENANDOAH_RP_PS_NumElements
+class ShenandoahWeakRoots {
+private:
+  WeakProcessorPhaseTimes _process_timings;
+  WeakProcessor::Task     _task;
+public:
+  ShenandoahWeakRoots(uint n_workers);
+  ~ShenandoahWeakRoots();
+
+  template <typename IsAlive, typename KeepAlive>
+  void oops_do(IsAlive* is_alive, KeepAlive* keep_alive, uint worker_id);
+};
+
+class ShenandoahStringDedupRoots {
+public:
+  ShenandoahStringDedupRoots();
+  ~ShenandoahStringDedupRoots();
+
+  void oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id);
+};
+
+template <typename ITR>
+class ShenandoahCodeCacheRoots {
+private:
+  ITR _coderoots_iterator;
+public:
+  ShenandoahCodeCacheRoots();
+  ~ShenandoahCodeCacheRoots();
+
+  void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id);
+};
+
+class ShenandoahClassLoaderDataRoots {
+public:
+  ShenandoahClassLoaderDataRoots();
+
+  void clds_do(CLDClosure* strong_clds, CLDClosure* weak_clds, uint worker_id);
 };
 
 class ShenandoahRootProcessor : public StackObj {
-  SubTasksDone* _process_strong_tasks;
-  StrongRootsScope _srs;
-  ShenandoahPhaseTimings::Phase _phase;
-  ParallelCLDRootIterator _cld_iterator;
-  ShenandoahAllCodeRootsIterator _coderoots_all_iterator;
-  CodeBlobClosure* _threads_nmethods_cl;
-  WeakProcessorPhaseTimes _weak_processor_timings;
-  WeakProcessor::Task     _weak_processor_task;
-  bool                    _processed_weak_roots;
-
-  void process_java_roots(OopClosure* scan_non_heap_roots,
-                          CLDClosure* scan_strong_clds,
-                          CLDClosure* scan_weak_clds,
-                          CodeBlobClosure* scan_strong_code,
-                          ThreadClosure* thread_cl,
-                          uint worker_i);
-
-  void process_vm_roots(OopClosure* scan_non_heap_roots,
-                        uint worker_i);
-
-  void weak_processor_timing_to_shenandoah_timing(const WeakProcessorPhases::Phase wpp,
-                                                  const ShenandoahPhaseTimings::GCParPhases spp,
-                                                  ShenandoahWorkerTimings* worker_times) const;
-
+private:
+  ShenandoahHeap* const               _heap;
+  const ShenandoahPhaseTimings::Phase _phase;
 public:
-  ShenandoahRootProcessor(ShenandoahHeap* heap, uint n_workers,
-                          ShenandoahPhaseTimings::Phase phase);
+  ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase phase);
   ~ShenandoahRootProcessor();
 
-  // Apply oops, clds and blobs to all strongly reachable roots in the system.
-  // Optionally, apply class loader closure to weak clds, depending on class unloading
-  // for the particular GC cycles.
-  void process_strong_roots(OopClosure* oops,
-                            CLDClosure* clds,
-                            CodeBlobClosure* blobs,
-                            ThreadClosure* thread_cl,
-                            uint worker_id);
+  ShenandoahHeap* heap() const { return _heap; }
+};
 
-  // Apply oops, clds and blobs to strongly reachable roots in the system
-  void process_all_roots(OopClosure* oops,
-                         CLDClosure* clds,
-                         CodeBlobClosure* blobs,
-                         ThreadClosure* thread_cl,
-                         uint worker_id);
+class ShenandoahRootScanner : public ShenandoahRootProcessor {
+private:
+  ShenandoahSerialRoots          _serial_roots;
+  ShenandoahClassLoaderDataRoots _cld_roots;
+  ShenandoahThreadRoots          _thread_roots;
+  ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator> _code_roots;
+public:
+  ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase);
 
-  // Apply oops, clds and blobs to strongly and weakly reachable roots in the system
-  template <typename IsAlive>
-  void update_all_roots(OopClosure* oops,
-                        CLDClosure* clds,
-                        CodeBlobClosure* blobs,
-                        ThreadClosure* thread_cl,
-                        uint worker_id);
+  // Apply oops, clds and blobs to all strongly reachable roots in the system,
+  // during class unloading cycle
+  void strong_roots_do(uint worker_id, OopClosure* cl);
+  void strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc = NULL);
 
-  // Number of worker threads used by the root processor.
-  uint n_workers() const;
+  // Apply oops, clds and blobs to all strongly reachable roots and weakly reachable
+  // 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);
 };
 
-class ShenandoahRootEvacuator : public StackObj {
-  SubTasksDone* _evacuation_tasks;
-  StrongRootsScope _srs;
-  ShenandoahPhaseTimings::Phase _phase;
-  ShenandoahCsetCodeRootsIterator _coderoots_cset_iterator;
-  ParallelCLDRootIterator _cld_iterator;
-  WeakProcessorPhaseTimes _weak_processor_timings;
-  WeakProcessor::Task     _weak_processor_task;
+// Evacuate all roots at a safepoint
+class ShenandoahRootEvacuator : public ShenandoahRootProcessor {
+private:
+  ShenandoahSerialRoots          _serial_roots;
+  ShenandoahClassLoaderDataRoots _cld_roots;
+  ShenandoahThreadRoots          _thread_roots;
+  ShenandoahWeakRoots            _weak_roots;
+  ShenandoahStringDedupRoots     _dedup_roots;
+  ShenandoahCodeCacheRoots<ShenandoahCsetCodeRootsIterator> _code_roots;
+
+public:
+  ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase);
+
+  void roots_do(uint worker_id, OopClosure* oops);
+};
 
-  enum Shenandoah_evacuate_roots_tasks {
-    SHENANDOAH_EVAC_Universe_oops_do,
-    SHENANDOAH_EVAC_ObjectSynchronizer_oops_do,
-    SHENANDOAH_EVAC_Management_oops_do,
-    SHENANDOAH_EVAC_SystemDictionary_oops_do,
-    SHENANDOAH_EVAC_jvmti_oops_do,
-    SHENANDOAH_EVAC_JNIHandles_oops_do,
-    // Leave this one last.
-    SHENANDOAH_EVAC_NumElements
-  };
+// Update all roots at a safepoint
+class ShenandoahRootUpdater : public ShenandoahRootProcessor {
+private:
+  ShenandoahSerialRoots          _serial_roots;
+  ShenandoahClassLoaderDataRoots _cld_roots;
+  ShenandoahThreadRoots          _thread_roots;
+  ShenandoahWeakRoots            _weak_roots;
+  ShenandoahStringDedupRoots     _dedup_roots;
+  ShenandoahCodeCacheRoots<ShenandoahCsetCodeRootsIterator> _code_roots;
+  const bool                     _update_code_cache;
+
 public:
-  ShenandoahRootEvacuator(ShenandoahHeap* heap, uint n_workers,
-                          ShenandoahPhaseTimings::Phase phase);
-  ~ShenandoahRootEvacuator();
+  ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool update_code_cache);
+
+  template<typename IsAlive, typename KeepAlive>
+  void roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive);
+};
 
-  void process_evacuate_roots(OopClosure* oops,
-                              CodeBlobClosure* blobs,
-                              uint worker_id);
+// Adjuster all roots at a safepoint during full gc
+class ShenandoahRootAdjuster : public ShenandoahRootProcessor {
+private:
+  ShenandoahSerialRoots          _serial_roots;
+  ShenandoahClassLoaderDataRoots _cld_roots;
+  ShenandoahThreadRoots          _thread_roots;
+  ShenandoahWeakRoots            _weak_roots;
+  ShenandoahStringDedupRoots     _dedup_roots;
+  ShenandoahCodeCacheRoots<ShenandoahAllCodeRootsIterator> _code_roots;
 
-  // Number of worker threads used by the root processor.
-  uint n_workers() const;
+public:
+  ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase);
+
+  void roots_do(uint worker_id, OopClosure* oops);
 };
+
 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp	Fri May 17 12:33:37 2019 +0200
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp	Fri May 17 09:52:35 2019 -0400
@@ -25,22 +25,47 @@
 #define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP
 
 #include "gc/shenandoah/shenandoahRootProcessor.hpp"
+#include "gc/shenandoah/shenandoahTimingTracker.hpp"
 
-template <typename IsAlive>
-void ShenandoahRootProcessor::update_all_roots(OopClosure* oops,
-                                               CLDClosure* clds,
-                                               CodeBlobClosure* blobs,
-                                               ThreadClosure* thread_cl,
-                                               uint worker_id) {
-  process_all_roots(oops, clds, blobs, thread_cl, worker_id);
+template <typename IsAlive, typename KeepAlive>
+void ShenandoahWeakRoots::oops_do(IsAlive* is_alive, KeepAlive* keep_alive, uint worker_id) {
+  _task.work<IsAlive, KeepAlive>(worker_id, is_alive, keep_alive);
+}
+
+template <typename ITR>
+ShenandoahCodeCacheRoots<ITR>::ShenandoahCodeCacheRoots() {
+  nmethod::oops_do_marking_prologue();
+}
+
+template <typename ITR>
+void ShenandoahCodeCacheRoots<ITR>::code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id) {
+  ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
+  ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id);
+  _coderoots_iterator.possibly_parallel_blobs_do(blob_cl);
+}
 
-  IsAlive is_alive;
-  _weak_processor_task.work<IsAlive, OopClosure>(worker_id, &is_alive, oops);
-  _processed_weak_roots = true;
+template <typename ITR>
+ShenandoahCodeCacheRoots<ITR>::~ShenandoahCodeCacheRoots() {
+  nmethod::oops_do_marking_epilogue();
+}
+
+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);
+  CLDToOopClosure clds(keep_alive, ClassLoaderData::_claim_strong);
+  CLDToOopClosure* weak_clds = ShenandoahHeap::heap()->unload_classes() ? NULL : &clds;
 
-  if (ShenandoahStringDedup::is_enabled()) {
-    ShenandoahStringDedup::parallel_oops_do(&is_alive, oops, worker_id);
+  _serial_roots.oops_do(keep_alive, worker_id);
+
+  _thread_roots.oops_do(keep_alive, NULL, worker_id);
+  _cld_roots.clds_do(&clds, weak_clds, worker_id);
+
+  if(_update_code_cache) {
+    _code_roots.code_blobs_do(&update_blobs, worker_id);
   }
+
+  _weak_roots.oops_do<IsAlive, KeepAlive>(is_alive, keep_alive, worker_id);
+  _dedup_roots.oops_do(is_alive, keep_alive, worker_id);
 }
 
 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp	Fri May 17 12:33:37 2019 +0200
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp	Fri May 17 09:52:35 2019 -0400
@@ -161,11 +161,13 @@
 
 class ShenandoahInitTraversalCollectionTask : public AbstractGangTask {
 private:
-  ShenandoahRootProcessor* _rp;
+  ShenandoahRootScanner* _rp;
   ShenandoahHeap* _heap;
   ShenandoahCsetCodeRootsIterator* _cset_coderoots;
+  ShenandoahStringDedupRoots       _dedup_roots;
+
 public:
-  ShenandoahInitTraversalCollectionTask(ShenandoahRootProcessor* rp, ShenandoahCsetCodeRootsIterator* cset_coderoots) :
+  ShenandoahInitTraversalCollectionTask(ShenandoahRootScanner* rp, ShenandoahCsetCodeRootsIterator* cset_coderoots) :
     AbstractGangTask("Shenandoah Init Traversal Collection"),
     _rp(rp),
     _heap(ShenandoahHeap::heap()),
@@ -191,18 +193,17 @@
       ShenandoahMarkCLDClosure cld_cl(&roots_cl);
       MarkingCodeBlobClosure code_cl(&roots_cl, CodeBlobToOopClosure::FixRelocations);
       if (unload_classes) {
-        _rp->process_strong_roots(&roots_cl, &cld_cl, NULL, NULL, worker_id);
+        _rp->strong_roots_do(worker_id, &roots_cl);
         // Need to pre-evac code roots here. Otherwise we might see from-space constants.
         ShenandoahWorkerTimings* worker_times = _heap->phase_timings()->worker_times();
         ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id);
         _cset_coderoots->possibly_parallel_blobs_do(&code_cl);
       } else {
-        _rp->process_all_roots(&roots_cl, &cld_cl, &code_cl, NULL, worker_id);
+        _rp->roots_do(worker_id, &roots_cl, &cld_cl, &code_cl);
       }
-      if (ShenandoahStringDedup::is_enabled()) {
-        AlwaysTrueClosure is_alive;
-        ShenandoahStringDedup::parallel_oops_do(&is_alive, &roots_cl, worker_id);
-      }
+
+      AlwaysTrueClosure is_alive;
+      _dedup_roots.oops_do(&is_alive, &roots_cl, worker_id);
     }
   }
 };
@@ -230,11 +231,11 @@
 
 class ShenandoahFinalTraversalCollectionTask : public AbstractGangTask {
 private:
-  ShenandoahRootProcessor* _rp;
+  ShenandoahRootScanner* _rp;
   ShenandoahTaskTerminator* _terminator;
   ShenandoahHeap* _heap;
 public:
-  ShenandoahFinalTraversalCollectionTask(ShenandoahRootProcessor* rp, ShenandoahTaskTerminator* terminator) :
+  ShenandoahFinalTraversalCollectionTask(ShenandoahRootScanner* rp, ShenandoahTaskTerminator* terminator) :
     AbstractGangTask("Shenandoah Final Traversal Collection"),
     _rp(rp),
     _terminator(terminator),
@@ -273,23 +274,23 @@
     // roots here.
     if (!_heap->is_degenerated_gc_in_progress()) {
       ShenandoahTraversalClosure roots_cl(q, rp);
-      CLDToOopClosure cld_cl(&roots_cl, ClassLoaderData::_claim_strong);
       ShenandoahTraversalSATBThreadsClosure tc(&satb_cl);
       if (unload_classes) {
         ShenandoahRemarkCLDClosure remark_cld_cl(&roots_cl);
-        _rp->process_strong_roots(&roots_cl, &remark_cld_cl, NULL, &tc, worker_id);
+        _rp->strong_roots_do(worker_id, &roots_cl, &remark_cld_cl, NULL, &tc);
       } else {
-        _rp->process_all_roots(&roots_cl, &cld_cl, NULL, &tc, worker_id);
+        CLDToOopClosure cld_cl(&roots_cl, ClassLoaderData::_claim_strong);
+        _rp->roots_do(worker_id, &roots_cl, &cld_cl, NULL, &tc);
       }
     } else {
       ShenandoahTraversalDegenClosure roots_cl(q, rp);
-      CLDToOopClosure cld_cl(&roots_cl, ClassLoaderData::_claim_strong);
       ShenandoahTraversalSATBThreadsClosure tc(&satb_cl);
       if (unload_classes) {
         ShenandoahRemarkCLDClosure remark_cld_cl(&roots_cl);
-        _rp->process_strong_roots(&roots_cl, &remark_cld_cl, NULL, &tc, worker_id);
+        _rp->strong_roots_do(worker_id, &roots_cl, &remark_cld_cl, NULL, &tc);
       } else {
-        _rp->process_all_roots(&roots_cl, &cld_cl, NULL, &tc, worker_id);
+        CLDToOopClosure cld_cl(&roots_cl, ClassLoaderData::_claim_strong);
+        _rp->roots_do(worker_id, &roots_cl, &cld_cl, NULL, &tc);
       }
     }
 
@@ -309,6 +310,9 @@
   _task_queues(new ShenandoahObjToScanQueueSet(heap->max_workers())),
   _traversal_set(ShenandoahHeapRegionSet()) {
 
+  // Traversal does not support concurrent code root scanning
+  FLAG_SET_DEFAULT(ShenandoahConcurrentScanCodeRoots, false);
+
   uint num_queues = heap->max_workers();
   for (uint i = 0; i < num_queues; ++i) {
     ShenandoahObjToScanQueue* task_queue = new ShenandoahObjToScanQueue();
@@ -411,7 +415,7 @@
     {
       uint nworkers = _heap->workers()->active_workers();
       task_queues()->reserve(nworkers);
-      ShenandoahRootProcessor rp(_heap, nworkers, ShenandoahPhaseTimings::init_traversal_gc_work);
+      ShenandoahRootScanner rp(nworkers, ShenandoahPhaseTimings::init_traversal_gc_work);
 
       ShenandoahCsetCodeRootsIterator cset_coderoots = ShenandoahCodeRoots::cset_iterator();
 
@@ -584,7 +588,7 @@
     task_queues()->reserve(nworkers);
 
     // Finish traversal
-    ShenandoahRootProcessor rp(_heap, nworkers, ShenandoahPhaseTimings::final_traversal_gc_work);
+    ShenandoahRootScanner rp(nworkers, ShenandoahPhaseTimings::final_traversal_gc_work);
     ShenandoahTerminationTracker term(ShenandoahPhaseTimings::final_traversal_gc_termination);
 
     ShenandoahTaskTerminator terminator(nworkers, task_queues());
@@ -693,10 +697,10 @@
 
 class ShenandoahTraversalFixRootsTask : public AbstractGangTask {
 private:
-  ShenandoahRootProcessor* _rp;
+  ShenandoahRootUpdater* _rp;
 
 public:
-  ShenandoahTraversalFixRootsTask(ShenandoahRootProcessor* rp) :
+  ShenandoahTraversalFixRootsTask(ShenandoahRootUpdater* rp) :
     AbstractGangTask("Shenandoah traversal fix roots"),
     _rp(rp) {
     assert(ShenandoahHeap::heap()->has_forwarded_objects(), "Must be");
@@ -705,9 +709,8 @@
   void work(uint worker_id) {
     ShenandoahParallelWorkerSession worker_session(worker_id);
     ShenandoahTraversalFixRootsClosure cl;
-    MarkingCodeBlobClosure blobsCl(&cl, CodeBlobToOopClosure::FixRelocations);
-    CLDToOopClosure cldCl(&cl, ClassLoaderData::_claim_strong);
-    _rp->update_all_roots<ShenandoahForwardedIsAliveClosure>(&cl, &cldCl, &blobsCl, NULL, worker_id);
+    ShenandoahForwardedIsAliveClosure is_alive;
+    _rp->roots_do<ShenandoahForwardedIsAliveClosure, ShenandoahTraversalFixRootsClosure>(worker_id, &is_alive, &cl);
   }
 };
 
@@ -715,7 +718,7 @@
 #if defined(COMPILER2) || INCLUDE_JVMCI
   DerivedPointerTable::clear();
 #endif
-  ShenandoahRootProcessor rp(_heap, _heap->workers()->active_workers(), ShenandoahPhaseTimings::final_traversal_update_roots);
+  ShenandoahRootUpdater rp(_heap->workers()->active_workers(), ShenandoahPhaseTimings::final_traversal_update_roots, true /* update code cache */);
   ShenandoahTraversalFixRootsTask update_roots_task(&rp);
   _heap->workers()->run_task(&update_roots_task);
 #if defined(COMPILER2) || INCLUDE_JVMCI