From 79e95a1b35d8fae79a70662a64a63fbb8a7aca9f Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 29 Apr 2026 12:34:03 +0000 Subject: [PATCH] 8383486: G1: Revise documentation about root scanning Reviewed-by: stefank, ayang --- src/hotspot/share/gc/g1/g1ConcurrentMark.hpp | 6 +++--- .../share/gc/g1/g1ConcurrentMarkThread.cpp | 17 ----------------- src/hotspot/share/gc/g1/g1YoungCollector.cpp | 6 +----- 3 files changed, 4 insertions(+), 25 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp index f9287f673d2..1ab4654a490 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp @@ -280,9 +280,9 @@ private: // Typically they contain the areas from TAMS to top of the regions. // We could scan and mark through these objects during the concurrent start pause, // but for pause time reasons we move this work to the concurrent phase. -// We need to complete this procedure before we can evacuate a particular region -// because evacuation might determine that some of these "root objects" are dead, -// potentially dropping some required references. +// Garbage collections that evacuate must either complete or abort this procedure +// before they can move objects because evacuation might determine that some of these +// "root objects" are dead, potentially dropping some references. // Root MemRegions comprise of the contents of survivor regions at the end // of the GC, and any objects copied into the old gen during GC. class G1CMRootMemRegions { diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp index b8c97acd1b0..8fc4d7a2e20 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp @@ -263,23 +263,6 @@ void G1ConcurrentMarkThread::concurrent_mark_cycle_do() { HandleMark hm(Thread::current()); ResourceMark rm; - // We have to ensure that we finish scanning the root regions - // before the next GC takes place. To ensure this we have to - // make sure that we do not join the STS until the root regions - // have been scanned. If we did then it's possible that a - // subsequent GC could block us from joining the STS and proceed - // without the root regions have been scanned which would be a - // correctness issue. - // - // So do not return before the scan root regions phase as a GC waits for a - // notification from it. - // - // For the same reason ConcurrentGCBreakpoints (in the phase methods) before - // here risk deadlock, because a young GC must wait for root region scanning. - // - // We can not easily abort before root region scan either because of the - // reasons mentioned in G1CollectedHeap::abort_concurrent_cycle(). - // Phase 1: Scan root regions. if (phase_scan_root_regions()) return; diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp index 9c12127c864..d26bcc23c08 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp @@ -246,8 +246,6 @@ G1YoungGCAllocationFailureInjector* G1YoungCollector::allocation_failure_injecto void G1YoungCollector::complete_root_region_scan() { Ticks start = Ticks::now(); - // We have to complete root region scan as it's the only way to ensure that all the - // objects on them have been correctly scanned before we start moving them during the GC. if (concurrent_mark()->complete_root_regions_scan_in_safepoint()) { phase_times()->record_root_region_scan_time((Ticks::now() - start).seconds() * MILLIUNITS); } @@ -1138,9 +1136,7 @@ void G1YoungCollector::collect() { // Individual parallel phases may override this. set_young_collection_default_active_worker_threads(); - // Wait for root region scan here to make sure that it is done before any - // use of the STW workers to maximize cpu use (i.e. all cores are available - // just to do that). + // Complete root region scan before moving any objects to preserve the SATB invariant. complete_root_region_scan(); G1YoungGCVerifierMark vm(this);