8375981: G1: Convert G1RemSet helper classes to use Atomic<T>

Reviewed-by: shade, iwalulya
This commit is contained in:
Thomas Schatzl 2026-01-26 09:15:32 +00:00
parent 2af271e5e6
commit e7cadd90b2

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2026, Oracle and/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
@ -50,7 +50,7 @@
#include "memory/resourceArea.hpp"
#include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomicAccess.hpp"
#include "runtime/atomic.hpp"
#include "runtime/os.hpp"
#include "utilities/align.hpp"
#include "utilities/globalDefinitions.hpp"
@ -107,46 +107,48 @@ class G1RemSetScanState : public CHeapObj<mtGC> {
// Set of (unique) regions that can be added to concurrently.
class G1DirtyRegions : public CHeapObj<mtGC> {
uint* _buffer;
uint _cur_idx;
Atomic<uint> _cur_idx;
size_t _max_reserved_regions;
bool* _contains;
Atomic<bool>* _contains;
public:
G1DirtyRegions(size_t max_reserved_regions) :
_buffer(NEW_C_HEAP_ARRAY(uint, max_reserved_regions, mtGC)),
_cur_idx(0),
_max_reserved_regions(max_reserved_regions),
_contains(NEW_C_HEAP_ARRAY(bool, max_reserved_regions, mtGC)) {
_contains(NEW_C_HEAP_ARRAY(Atomic<bool>, max_reserved_regions, mtGC)) {
reset();
}
~G1DirtyRegions() {
FREE_C_HEAP_ARRAY(uint, _buffer);
FREE_C_HEAP_ARRAY(bool, _contains);
FREE_C_HEAP_ARRAY(Atomic<bool>, _contains);
}
void reset() {
_cur_idx = 0;
::memset(_contains, false, _max_reserved_regions * sizeof(bool));
_cur_idx.store_relaxed(0);
for (uint i = 0; i < _max_reserved_regions; i++) {
_contains[i].store_relaxed(false);
}
}
uint size() const { return _cur_idx; }
uint size() const { return _cur_idx.load_relaxed(); }
uint at(uint idx) const {
assert(idx < _cur_idx, "Index %u beyond valid regions", idx);
assert(idx < size(), "Index %u beyond valid regions", idx);
return _buffer[idx];
}
void add_dirty_region(uint region) {
if (_contains[region]) {
if (_contains[region].load_relaxed()) {
return;
}
bool marked_as_dirty = AtomicAccess::cmpxchg(&_contains[region], false, true) == false;
bool marked_as_dirty = _contains[region].compare_set(false, true);
if (marked_as_dirty) {
uint allocated = AtomicAccess::fetch_then_add(&_cur_idx, 1u);
uint allocated = _cur_idx.fetch_then_add(1u);
_buffer[allocated] = region;
}
}
@ -155,9 +157,11 @@ class G1RemSetScanState : public CHeapObj<mtGC> {
void merge(const G1DirtyRegions* other) {
for (uint i = 0; i < other->size(); i++) {
uint region = other->at(i);
if (!_contains[region]) {
_buffer[_cur_idx++] = region;
_contains[region] = true;
if (!_contains[region].load_relaxed()) {
uint cur = _cur_idx.load_relaxed();
_buffer[cur] = region;
_cur_idx.store_relaxed(cur + 1);
_contains[region].store_relaxed(true);
}
}
}
@ -173,7 +177,7 @@ class G1RemSetScanState : public CHeapObj<mtGC> {
class G1ClearCardTableTask : public G1AbstractSubTask {
G1CollectedHeap* _g1h;
G1DirtyRegions* _regions;
uint volatile _cur_dirty_regions;
Atomic<uint> _cur_dirty_regions;
G1RemSetScanState* _scan_state;
@ -210,8 +214,9 @@ class G1ClearCardTableTask : public G1AbstractSubTask {
void do_work(uint worker_id) override {
const uint num_regions_per_worker = num_cards_per_worker / (uint)G1HeapRegion::CardsPerRegion;
while (_cur_dirty_regions < _regions->size()) {
uint next = AtomicAccess::fetch_then_add(&_cur_dirty_regions, num_regions_per_worker);
uint cur = _cur_dirty_regions.load_relaxed();
while (cur < _regions->size()) {
uint next = _cur_dirty_regions.fetch_then_add(num_regions_per_worker);
uint max = MIN2(next + num_regions_per_worker, _regions->size());
for (uint i = next; i < max; i++) {
@ -226,6 +231,7 @@ class G1ClearCardTableTask : public G1AbstractSubTask {
// old regions use it for old->collection set candidates, so they should not be cleared
// either.
}
cur = max;
}
}
};
@ -1115,7 +1121,7 @@ class G1MergeHeapRootsTask : public WorkerTask {
bool _initial_evacuation;
volatile bool _fast_reclaim_handled;
Atomic<bool> _fast_reclaim_handled;
public:
G1MergeHeapRootsTask(G1RemSetScanState* scan_state, uint num_workers, bool initial_evacuation) :
@ -1143,8 +1149,8 @@ public:
// 1. eager-reclaim candidates
if (_initial_evacuation &&
g1h->has_humongous_reclaim_candidates() &&
!_fast_reclaim_handled &&
!AtomicAccess::cmpxchg(&_fast_reclaim_handled, false, true)) {
!_fast_reclaim_handled.load_relaxed() &&
_fast_reclaim_handled.compare_set(false, true)) {
G1GCParPhaseTimesTracker subphase_x(p, G1GCPhaseTimes::MergeER, worker_id);