diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 4f45821a889..a3d45a98354 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -22,6 +22,7 @@ * */ +#include "classfile/classLoaderDataGraph.hpp" #include "gc/serial/cardTableRS.hpp" #include "gc/serial/serialGcRefProcProxyTask.hpp" #include "gc/serial/serialHeap.inline.hpp" @@ -38,8 +39,10 @@ #include "gc/shared/gcTimer.hpp" #include "gc/shared/gcTrace.hpp" #include "gc/shared/gcTraceTime.inline.hpp" +#include "gc/shared/oopStorageSet.inline.hpp" #include "gc/shared/referencePolicy.hpp" #include "gc/shared/referenceProcessorPhaseTimes.hpp" +#include "gc/shared/scavengableNMethods.hpp" #include "gc/shared/space.hpp" #include "gc/shared/spaceDecorator.hpp" #include "gc/shared/strongRootsScope.hpp" @@ -605,21 +608,31 @@ bool DefNewGeneration::collect(bool clear_all_soft_refs) { { StrongRootsScope srs(0); - RootScanClosure root_cl{this}; - CLDScanClosure cld_cl{this}; + RootScanClosure oop_closure{this}; + CLDScanClosure cld_closure{this}; - MarkingNMethodClosure code_cl(&root_cl, - NMethodToOopClosure::FixRelocations, - false /* keepalive_nmethods */); + MarkingNMethodClosure nmethod_closure(&oop_closure, + NMethodToOopClosure::FixRelocations, + false /* keepalive_nmethods */); - HeapWord* saved_top_in_old_gen = _old_gen->space()->top(); - heap->process_roots(SerialHeap::SO_ScavengeCodeCache, - &root_cl, - &cld_cl, - &cld_cl, - &code_cl); + // Starting tracing from roots, there are 4 kinds of roots in young-gc. + // + // 1. old-to-young pointers; processing them before relocating other kinds + // of roots. + _old_gen->scan_old_to_young_refs(); - _old_gen->scan_old_to_young_refs(saved_top_in_old_gen); + // 2. CLD; visit all (strong+weak) clds with the same closure, because we + // don't perform class unloading during young-gc. + ClassLoaderDataGraph::cld_do(&cld_closure); + + // 3. Threads stack frames and nmethods. + // Only nmethods that contain pointers into-young need to be processed + // during young-gc, and they are tracked in ScavengableNMethods + Threads::oops_do(&oop_closure, nullptr); + ScavengableNMethods::nmethods_do(&nmethod_closure); + + // 4. VM internal roots. + OopStorageSet::strong_oops_do(&oop_closure); } // "evacuate followers". diff --git a/src/hotspot/share/gc/serial/serialFullGC.cpp b/src/hotspot/share/gc/serial/serialFullGC.cpp index da5b8ba53a0..6eacb08f218 100644 --- a/src/hotspot/share/gc/serial/serialFullGC.cpp +++ b/src/hotspot/share/gc/serial/serialFullGC.cpp @@ -49,6 +49,7 @@ #include "gc/shared/gcTrace.hpp" #include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/modRefBarrierSet.hpp" +#include "gc/shared/oopStorageSet.inline.hpp" #include "gc/shared/preservedMarks.inline.hpp" #include "gc/shared/referencePolicy.hpp" #include "gc/shared/referenceProcessorPhaseTimes.hpp" @@ -66,6 +67,7 @@ #include "oops/oop.inline.hpp" #include "oops/typeArrayOop.inline.hpp" #include "runtime/prefetch.inline.hpp" +#include "runtime/threads.hpp" #include "utilities/align.hpp" #include "utilities/copy.hpp" #include "utilities/events.hpp" @@ -483,13 +485,22 @@ void SerialFullGC::phase1_mark(bool clear_all_softrefs) { { StrongRootsScope srs(0); - CLDClosure* weak_cld_closure = ClassUnloading ? nullptr : &follow_cld_closure; - MarkingNMethodClosure mark_code_closure(&follow_root_closure, !NMethodToOopClosure::FixRelocations, true); - gch->process_roots(SerialHeap::SO_None, - &follow_root_closure, - &follow_cld_closure, - weak_cld_closure, - &mark_code_closure); + MarkingNMethodClosure mark_code_closure(&follow_root_closure, + !NMethodToOopClosure::FixRelocations, + true); + + // Start tracing from roots, there are 3 kinds of roots in full-gc. + // + // 1. CLD. This method internally takes care of whether class loading is + // enabled or not, applying the closure to both strong and weak or only + // strong CLDs. + ClassLoaderDataGraph::always_strong_cld_do(&follow_cld_closure); + + // 2. Threads stack frames and active nmethods in them. + Threads::oops_do(&follow_root_closure, &mark_code_closure); + + // 3. VM internal roots. + OopStorageSet::strong_oops_do(&follow_root_closure); } // Process reference objects found during marking @@ -717,13 +728,20 @@ void SerialFullGC::invoke_at_safepoint(bool clear_all_softrefs) { ClassLoaderDataGraph::verify_claimed_marks_cleared(ClassLoaderData::_claim_stw_fullgc_adjust); - NMethodToOopClosure code_closure(&adjust_pointer_closure, NMethodToOopClosure::FixRelocations); - gch->process_roots(SerialHeap::SO_AllCodeCache, - &adjust_pointer_closure, - &adjust_cld_closure, - &adjust_cld_closure, - &code_closure); + // Remap strong and weak roots in adjust phase. + // 1. All (strong and weak) CLDs. + ClassLoaderDataGraph::cld_do(&adjust_cld_closure); + // 2. Threads stack frames. No need to visit on-stack nmethods, because all + // nmethods are visited in one go via CodeCache::nmethods_do. + Threads::oops_do(&adjust_pointer_closure, nullptr); + NMethodToOopClosure nmethod_cl(&adjust_pointer_closure, NMethodToOopClosure::FixRelocations); + CodeCache::nmethods_do(&nmethod_cl); + + // 3. VM internal roots + OopStorageSet::strong_oops_do(&adjust_pointer_closure); + + // 4. VM internal weak roots WeakProcessor::oops_do(&adjust_pointer_closure); adjust_marks(); diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp index fbbaabf618a..d6d51eef453 100644 --- a/src/hotspot/share/gc/serial/serialHeap.cpp +++ b/src/hotspot/share/gc/serial/serialHeap.cpp @@ -513,38 +513,6 @@ HeapWord* SerialHeap::satisfy_failed_allocation(size_t size, bool is_tlab) { return nullptr; } -void SerialHeap::process_roots(ScanningOption so, - OopClosure* strong_roots, - CLDClosure* strong_cld_closure, - CLDClosure* weak_cld_closure, - NMethodToOopClosure* code_roots) { - // General roots. - assert(code_roots != nullptr, "code root closure should always be set"); - - ClassLoaderDataGraph::roots_cld_do(strong_cld_closure, weak_cld_closure); - - // Only process code roots from thread stacks if we aren't visiting the entire CodeCache anyway - NMethodToOopClosure* roots_from_code_p = (so & SO_AllCodeCache) ? nullptr : code_roots; - - Threads::oops_do(strong_roots, roots_from_code_p); - - OopStorageSet::strong_oops_do(strong_roots); - - if (so & SO_ScavengeCodeCache) { - assert(code_roots != nullptr, "must supply closure for code cache"); - - // We only visit parts of the CodeCache when scavenging. - ScavengableNMethods::nmethods_do(code_roots); - } - if (so & SO_AllCodeCache) { - assert(code_roots != nullptr, "must supply closure for code cache"); - - // CMSCollector uses this to do intermediate-strength collections. - // We scan the entire code cache, since CodeCache::do_unloading is not called. - CodeCache::nmethods_do(code_roots); - } -} - template static void oop_iterate_from(OopClosureType* blk, ContiguousSpace* space, HeapWord** from) { assert(*from != nullptr, "precondition"); diff --git a/src/hotspot/share/gc/serial/serialHeap.hpp b/src/hotspot/share/gc/serial/serialHeap.hpp index d93e895d209..e86eac58515 100644 --- a/src/hotspot/share/gc/serial/serialHeap.hpp +++ b/src/hotspot/share/gc/serial/serialHeap.hpp @@ -222,23 +222,7 @@ public: // generations in a fully generational heap. CardTableRS* rem_set() { return _rem_set; } - // The ScanningOption determines which of the roots - // the closure is applied to: - // "SO_None" does none; - enum ScanningOption { - SO_None = 0x0, - SO_AllCodeCache = 0x8, - SO_ScavengeCodeCache = 0x10 - }; - public: - // Apply closures on various roots in Young GC or marking/adjust phases of Full GC. - void process_roots(ScanningOption so, - OopClosure* strong_roots, - CLDClosure* strong_cld_closure, - CLDClosure* weak_cld_closure, - NMethodToOopClosure* code_roots); - // Set the saved marks of generations, if that makes sense. // In particular, if any generation might iterate over the oops // in other generations, it should call this method. diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.cpp b/src/hotspot/share/gc/serial/tenuredGeneration.cpp index 589e670a2e4..a28a8c8e1cb 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp @@ -277,8 +277,8 @@ HeapWord* TenuredGeneration::block_start(const void* addr) const { } } -void TenuredGeneration::scan_old_to_young_refs(HeapWord* saved_top_in_old_gen) { - _rs->scan_old_to_young_refs(this, saved_top_in_old_gen); +void TenuredGeneration::scan_old_to_young_refs() { + _rs->scan_old_to_young_refs(this, space()->top()); } TenuredGeneration::TenuredGeneration(ReservedSpace rs, diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.hpp b/src/hotspot/share/gc/serial/tenuredGeneration.hpp index 1f6871d8ee2..892fc5bb86c 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.hpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.hpp @@ -104,7 +104,7 @@ public: HeapWord* block_start(const void* addr) const; - void scan_old_to_young_refs(HeapWord* saved_top_in_old_gen); + void scan_old_to_young_refs(); bool is_in(const void* p) const;