8373941: Epsilon: Robust counter updates in early VM phases

Reviewed-by: stefank, tschatzl
This commit is contained in:
Aleksey Shipilev 2026-01-09 12:24:13 +00:00
parent c8c6e7007a
commit 47e19353cd
5 changed files with 106 additions and 13 deletions

View File

@ -77,6 +77,7 @@ jint EpsilonHeap::initialize() {
void EpsilonHeap::initialize_serviceability() {
_pool = new EpsilonMemoryPool(this);
_memory_manager.add_pool(_pool);
_monitoring_support->mark_ready();
}
GrowableArray<GCMemoryManager*> EpsilonHeap::memory_managers() {
@ -101,7 +102,7 @@ EpsilonHeap* EpsilonHeap::heap() {
return named_heap<EpsilonHeap>(CollectedHeap::Epsilon);
}
HeapWord* EpsilonHeap::allocate_work(size_t size, bool verbose) {
HeapWord* EpsilonHeap::allocate_work(size_t size) {
assert(is_object_aligned(size), "Allocation size should be aligned: %zu", size);
HeapWord* res = nullptr;
@ -151,19 +152,23 @@ HeapWord* EpsilonHeap::allocate_work(size_t size, bool verbose) {
size_t used = _space->used();
// Allocation successful, update counters
if (verbose) {
size_t last = _last_counter_update;
if ((used - last >= _step_counter_update) && AtomicAccess::cmpxchg(&_last_counter_update, last, used) == last) {
// Allocation successful, update counters and print status.
// At this point, some diagnostic subsystems might not yet be initialized.
// We pretend the printout happened either way. This keeps allocation path
// from obsessively checking the subsystems' status on every allocation.
size_t last_counter = AtomicAccess::load(&_last_counter_update);
if ((used - last_counter >= _step_counter_update) &&
AtomicAccess::cmpxchg(&_last_counter_update, last_counter, used) == last_counter) {
if (_monitoring_support->is_ready()) {
_monitoring_support->update_counters();
}
}
// ...and print the occupancy line, if needed
if (verbose) {
size_t last = _last_heap_print;
if ((used - last >= _step_heap_print) && AtomicAccess::cmpxchg(&_last_heap_print, last, used) == last) {
print_heap_info(used);
size_t last_heap = AtomicAccess::load(&_last_heap_print);
if ((used - last_heap >= _step_heap_print) &&
AtomicAccess::cmpxchg(&_last_heap_print, last_heap, used) == last_heap) {
print_heap_info(used);
if (Metaspace::initialized()) {
print_metaspace_info();
}
}
@ -265,8 +270,7 @@ HeapWord* EpsilonHeap::mem_allocate(size_t size) {
}
HeapWord* EpsilonHeap::allocate_loaded_archive_space(size_t size) {
// Cannot use verbose=true because Metaspace is not initialized
return allocate_work(size, /* verbose = */false);
return allocate_work(size);
}
void EpsilonHeap::collect(GCCause::Cause cause) {

View File

@ -83,7 +83,7 @@ public:
bool requires_barriers(stackChunkOop obj) const override { return false; }
// Allocation
HeapWord* allocate_work(size_t size, bool verbose = true);
HeapWord* allocate_work(size_t size);
HeapWord* mem_allocate(size_t size) override;
HeapWord* allocate_new_tlab(size_t min_size,
size_t requested_size,

View File

@ -96,9 +96,11 @@ public:
EpsilonMonitoringSupport::EpsilonMonitoringSupport(EpsilonHeap* heap) {
_heap_counters = new EpsilonGenerationCounters(heap);
_space_counters = new EpsilonSpaceCounters("Heap", 0, heap->max_capacity(), 0, _heap_counters);
_ready = false;
}
void EpsilonMonitoringSupport::update_counters() {
assert(is_ready(), "Must be ready");
MemoryService::track_memory_usage();
if (UsePerfData) {
@ -110,3 +112,11 @@ void EpsilonMonitoringSupport::update_counters() {
MetaspaceCounters::update_performance_counters();
}
}
bool EpsilonMonitoringSupport::is_ready() {
return AtomicAccess::load_acquire(&_ready);
}
void EpsilonMonitoringSupport::mark_ready() {
return AtomicAccess::release_store(&_ready, true);
}

View File

@ -35,9 +35,12 @@ class EpsilonMonitoringSupport : public CHeapObj<mtGC> {
private:
EpsilonGenerationCounters* _heap_counters;
EpsilonSpaceCounters* _space_counters;
volatile bool _ready;
public:
EpsilonMonitoringSupport(EpsilonHeap* heap);
bool is_ready();
void mark_ready();
void update_counters();
};

View File

@ -0,0 +1,76 @@
/*
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package gc.epsilon;
/**
* @test TestInitAllocs
* @requires vm.gc.Epsilon
* @summary Test that allocation path taken in early JVM phases works
*
* @run main/othervm -Xmx256m
* -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
* gc.epsilon.TestInitAllocs
*
* @run main/othervm -Xmx256m
* -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
* -XX:+UseTLAB
* -XX:+UseCompressedOops
* -XX:EpsilonMinHeapExpand=1024
* -XX:EpsilonUpdateCountersStep=1
* -XX:EpsilonPrintHeapSteps=1000000
* gc.epsilon.TestInitAllocs
*
* @run main/othervm -Xmx256m
* -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
* -XX:+UseTLAB
* -XX:-UseCompressedOops
* -XX:EpsilonMinHeapExpand=1024
* -XX:EpsilonUpdateCountersStep=1
* -XX:EpsilonPrintHeapSteps=1000000
* gc.epsilon.TestInitAllocs
*
* @run main/othervm -Xmx256m
* -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
* -XX:-UseTLAB
* -XX:+UseCompressedOops
* -XX:EpsilonMinHeapExpand=1024
* -XX:EpsilonUpdateCountersStep=1
* -XX:EpsilonPrintHeapSteps=1000000
* gc.epsilon.TestInitAllocs
*
* @run main/othervm -Xmx256m
* -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
* -XX:-UseTLAB
* -XX:-UseCompressedOops
* -XX:EpsilonMinHeapExpand=1024
* -XX:EpsilonUpdateCountersStep=1
* -XX:EpsilonPrintHeapSteps=1000000
* gc.epsilon.TestInitAllocs
*/
public class TestInitAllocs {
public static void main(String[] args) throws Exception {
System.out.println("Hello World");
}
}