8361055: Serial: Inline SerialHeap::process_roots

Reviewed-by: tschatzl, kbarrett, stefank
This commit is contained in:
Albert Mingkun Yang 2025-07-28 07:15:40 +00:00
parent 3b0da29879
commit af5932efb5
6 changed files with 59 additions and 76 deletions

View File

@ -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".

View File

@ -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();

View File

@ -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 <typename OopClosureType>
static void oop_iterate_from(OopClosureType* blk, ContiguousSpace* space, HeapWord** from) {
assert(*from != nullptr, "precondition");

View File

@ -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.

View File

@ -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,

View File

@ -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;