hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp
changeset 33213 b937f634f56e
parent 32617 a59435e1fecc
child 37985 539c597ee0fa
--- a/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp	Wed Oct 14 09:33:45 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp	Wed Oct 14 14:50:43 2015 +0200
@@ -33,7 +33,7 @@
 #include "gc/g1/g1CollectorPolicy.hpp"
 #include "gc/g1/g1CollectorState.hpp"
 #include "gc/g1/g1GCPhaseTimes.hpp"
-#include "gc/g1/g1RemSet.inline.hpp"
+#include "gc/g1/g1RootClosures.hpp"
 #include "gc/g1/g1RootProcessor.hpp"
 #include "gc/g1/heapRegion.inline.hpp"
 #include "memory/allocation.inline.hpp"
@@ -70,40 +70,19 @@
     _lock(Mutex::leaf, "G1 Root Scanning barrier lock", false, Monitor::_safepoint_check_never),
     _n_workers_discovered_strong_classes(0) {}
 
-void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots,
-                                     OopClosure* scan_non_heap_weak_roots,
-                                     CLDClosure* scan_strong_clds,
-                                     CLDClosure* scan_weak_clds,
-                                     bool trace_metadata,
-                                     uint worker_i) {
-  // First scan the shared roots.
+void G1RootProcessor::evacuate_roots(G1EvacuationRootClosures* closures, uint worker_i) {
   double ext_roots_start = os::elapsedTime();
   G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times();
 
-  BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots);
-  BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots);
-
-  OopClosure* const weak_roots = &buf_scan_non_heap_weak_roots;
-  OopClosure* const strong_roots = &buf_scan_non_heap_roots;
-
-  // CodeBlobClosures are not interoperable with BufferingOopClosures
-  G1CodeBlobClosure root_code_blobs(scan_non_heap_roots);
-
-  process_java_roots(strong_roots,
-                     trace_metadata ? scan_strong_clds : NULL,
-                     scan_strong_clds,
-                     trace_metadata ? NULL : scan_weak_clds,
-                     &root_code_blobs,
-                     phase_times,
-                     worker_i);
+  process_java_roots(closures, phase_times, worker_i);
 
   // This is the point where this worker thread will not find more strong CLDs/nmethods.
   // Report this so G1 can synchronize the strong and weak CLDs/nmethods processing.
-  if (trace_metadata) {
+  if (closures->trace_metadata()) {
     worker_has_discovered_all_strong_classes();
   }
 
-  process_vm_roots(strong_roots, weak_roots, phase_times, worker_i);
+  process_vm_roots(closures, phase_times, worker_i);
 
   {
     // Now the CM ref_processor roots.
@@ -113,11 +92,11 @@
       // concurrent mark ref processor as roots and keep entries
       // (which are added by the marking threads) on them live
       // until they can be processed at the end of marking.
-      _g1h->ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots);
+      _g1h->ref_processor_cm()->weak_oops_do(closures->strong_oops());
     }
   }
 
-  if (trace_metadata) {
+  if (closures->trace_metadata()) {
     {
       G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WaitForStrongCLD, worker_i);
       // Barrier to make sure all workers passed
@@ -127,18 +106,18 @@
 
     // Now take the complement of the strong CLDs.
     G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WeakCLDRoots, worker_i);
-    ClassLoaderDataGraph::roots_cld_do(NULL, scan_weak_clds);
+    assert(closures->second_pass_weak_clds() != NULL, "Should be non-null if we are tracing metadata.");
+    ClassLoaderDataGraph::roots_cld_do(NULL, closures->second_pass_weak_clds());
   } else {
     phase_times->record_time_secs(G1GCPhaseTimes::WaitForStrongCLD, worker_i, 0.0);
     phase_times->record_time_secs(G1GCPhaseTimes::WeakCLDRoots, worker_i, 0.0);
+    assert(closures->second_pass_weak_clds() == NULL, "Should be null if not tracing metadata.");
   }
 
   // Finish up any enqueued closure apps (attributed as object copy time).
-  buf_scan_non_heap_roots.done();
-  buf_scan_non_heap_weak_roots.done();
+  closures->flush();
 
-  double obj_copy_time_sec = buf_scan_non_heap_roots.closure_app_seconds()
-      + buf_scan_non_heap_weak_roots.closure_app_seconds();
+  double obj_copy_time_sec = closures->closure_app_seconds();
 
   phase_times->record_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, obj_copy_time_sec);
 
@@ -159,22 +138,68 @@
   _process_strong_tasks.all_tasks_completed(n_workers());
 }
 
+// Adaptor to pass the closures to the strong roots in the VM.
+class StrongRootsClosures : public G1RootClosures {
+  OopClosure* _roots;
+  CLDClosure* _clds;
+  CodeBlobClosure* _blobs;
+public:
+  StrongRootsClosures(OopClosure* roots, CLDClosure* clds, CodeBlobClosure* blobs) :
+      _roots(roots), _clds(clds), _blobs(blobs) {}
+
+  OopClosure* weak_oops()   { return NULL; }
+  OopClosure* strong_oops() { return _roots; }
+
+  CLDClosure* weak_clds()        { return NULL; }
+  CLDClosure* strong_clds()      { return _clds; }
+  CLDClosure* thread_root_clds() { return _clds; }
+
+  CodeBlobClosure* strong_codeblobs() { return _blobs; }
+};
+
 void G1RootProcessor::process_strong_roots(OopClosure* oops,
                                            CLDClosure* clds,
                                            CodeBlobClosure* blobs) {
+  StrongRootsClosures closures(oops, clds, blobs);
 
-  process_java_roots(oops, clds, clds, NULL, blobs, NULL, 0);
-  process_vm_roots(oops, NULL, NULL, 0);
+  process_java_roots(&closures, NULL, 0);
+  process_vm_roots(&closures, NULL, 0);
 
   _process_strong_tasks.all_tasks_completed(n_workers());
 }
 
+// Adaptor to pass the closures to all the roots in the VM.
+class AllRootsClosures : public G1RootClosures {
+  OopClosure* _roots;
+  CLDClosure* _clds;
+public:
+  AllRootsClosures(OopClosure* roots, CLDClosure* clds) :
+      _roots(roots), _clds(clds) {}
+
+  OopClosure* weak_oops() { return _roots; }
+  OopClosure* strong_oops() { return _roots; }
+
+  // By returning the same CLDClosure for both weak and strong CLDs we ensure
+  // that a single walk of the CLDG will invoke the closure on all CLDs i the
+  // system.
+  CLDClosure* weak_clds() { return _clds; }
+  CLDClosure* strong_clds() { return _clds; }
+  // We don't want to visit CLDs more than once, so we return NULL for the
+  // thread root CLDs.
+  CLDClosure* thread_root_clds() { return NULL; }
+
+  // We don't want to visit code blobs more than once, so we return NULL for the
+  // strong case and walk the entire code cache as a separate step.
+  CodeBlobClosure* strong_codeblobs() { return NULL; }
+};
+
 void G1RootProcessor::process_all_roots(OopClosure* oops,
                                         CLDClosure* clds,
                                         CodeBlobClosure* blobs) {
+  AllRootsClosures closures(oops, clds);
 
-  process_java_roots(oops, NULL, clds, clds, NULL, NULL, 0);
-  process_vm_roots(oops, oops, NULL, 0);
+  process_java_roots(&closures, NULL, 0);
+  process_vm_roots(&closures, NULL, 0);
 
   if (!_process_strong_tasks.is_task_claimed(G1RP_PS_CodeCache_oops_do)) {
     CodeCache::blobs_do(blobs);
@@ -183,35 +208,36 @@
   _process_strong_tasks.all_tasks_completed(n_workers());
 }
 
-void G1RootProcessor::process_java_roots(OopClosure* strong_roots,
-                                         CLDClosure* thread_stack_clds,
-                                         CLDClosure* strong_clds,
-                                         CLDClosure* weak_clds,
-                                         CodeBlobClosure* strong_code,
+void G1RootProcessor::process_java_roots(G1RootClosures* closures,
                                          G1GCPhaseTimes* phase_times,
                                          uint worker_i) {
-  assert(thread_stack_clds == NULL || weak_clds == NULL, "There is overlap between those, only one may be set");
+  assert(closures->thread_root_clds() == NULL || closures->weak_clds() == NULL, "There is overlap between those, only one may be set");
   // 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.
   {
     G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CLDGRoots, worker_i);
     if (!_process_strong_tasks.is_task_claimed(G1RP_PS_ClassLoaderDataGraph_oops_do)) {
-      ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds);
+      ClassLoaderDataGraph::roots_cld_do(closures->strong_clds(), closures->weak_clds());
     }
   }
 
   {
     G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ThreadRoots, worker_i);
     bool is_par = n_workers() > 1;
-    Threads::possibly_parallel_oops_do(is_par, strong_roots, thread_stack_clds, strong_code);
+    Threads::possibly_parallel_oops_do(is_par,
+                                       closures->strong_oops(),
+                                       closures->thread_root_clds(),
+                                       closures->strong_codeblobs());
   }
 }
 
-void G1RootProcessor::process_vm_roots(OopClosure* strong_roots,
-                                       OopClosure* weak_roots,
+void G1RootProcessor::process_vm_roots(G1RootClosures* closures,
                                        G1GCPhaseTimes* phase_times,
                                        uint worker_i) {
+  OopClosure* strong_roots = closures->strong_oops();
+  OopClosure* weak_roots = closures->weak_oops();
+
   {
     G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::UniverseRoots, worker_i);
     if (!_process_strong_tasks.is_task_claimed(G1RP_PS_Universe_oops_do)) {