# HG changeset patch # User zgu # Date 1560969153 14400 # Wed Jun 19 14:32:33 2019 -0400 # Node ID 3f41d6e72f74e92fe0fbcd8c4ef502aa58907ef1 # Parent e9da3a44a7edc0222e727b83bd758b9e43176cee 8226413: Shenandoah: Separate root scanner for SH::object_iterate() diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -1279,14 +1279,14 @@ Stack 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 _jni_roots; + ShenandoahJNIHandleRoots _jni_roots; public: ShenandoahConcurrentRootsEvacUpdateTask() : diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp @@ -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(&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); + } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp @@ -114,6 +114,7 @@ void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id); }; +template class ShenandoahClassLoaderDataRoots { public: ShenandoahClassLoaderDataRoots(); @@ -135,11 +136,11 @@ template class ShenandoahRootScanner : public ShenandoahRootProcessor { private: - ShenandoahSerialRoots _serial_roots; - ShenandoahJNIHandleRoots _jni_roots; - ShenandoahClassLoaderDataRoots _cld_roots; - ShenandoahThreadRoots _thread_roots; - ShenandoahCodeCacheRoots _code_roots; + ShenandoahSerialRoots _serial_roots; + ShenandoahThreadRoots _thread_roots; + ShenandoahCodeCacheRoots _code_roots; + ShenandoahJNIHandleRoots _jni_roots; + ShenandoahClassLoaderDataRoots _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 ShenandoahAllRootScanner; typedef ShenandoahRootScanner 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 _jni_roots; + ShenandoahClassLoaderDataRoots _cld_roots; + ShenandoahCodeCacheRoots _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 _jni_roots; - ShenandoahClassLoaderDataRoots _cld_roots; + ShenandoahClassLoaderDataRoots _cld_roots; ShenandoahThreadRoots _thread_roots; ShenandoahWeakRoots _weak_roots; ShenandoahStringDedupRoots _dedup_roots; @@ -183,7 +198,7 @@ private: ShenandoahSerialRoots _serial_roots; ShenandoahJNIHandleRoots _jni_roots; - ShenandoahClassLoaderDataRoots _cld_roots; + ShenandoahClassLoaderDataRoots _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 _jni_roots; - ShenandoahClassLoaderDataRoots _cld_roots; - ShenandoahThreadRoots _thread_roots; - ShenandoahWeakRoots _weak_roots; - ShenandoahStringDedupRoots _dedup_roots; - ShenandoahCodeCacheRoots _code_roots; + ShenandoahSerialRoots _serial_roots; + ShenandoahJNIHandleRoots _jni_roots; + ShenandoahClassLoaderDataRoots _cld_roots; + ShenandoahThreadRoots _thread_roots; + ShenandoahWeakRoots _weak_roots; + ShenandoahStringDedupRoots _dedup_roots; + ShenandoahCodeCacheRoots _code_roots; public: ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp @@ -31,6 +31,7 @@ #include "gc/shenandoah/shenandoahTimingTracker.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "memory/resourceArea.hpp" +#include "runtime/safepoint.hpp" template ShenandoahJNIHandleRoots::ShenandoahJNIHandleRoots() : @@ -54,6 +55,27 @@ _task.work(worker_id, is_alive, keep_alive); } +template +ShenandoahClassLoaderDataRoots::ShenandoahClassLoaderDataRoots() { + if (!SINGLE_THREADED) { + ClassLoaderDataGraph::clear_claimed_marks(); + } +} + +template +void ShenandoahClassLoaderDataRoots::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 ShenandoahCodeCacheRoots::ShenandoahCodeCacheRoots() { nmethod::oops_do_marking_prologue(); @@ -131,33 +153,6 @@ } template -void ShenandoahRootScanner::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 -void ShenandoahRootScanner::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 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);