--- 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)) {