mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
8375981: G1: Convert G1RemSet helper classes to use Atomic<T>
Reviewed-by: shade, iwalulya
This commit is contained in:
parent
2af271e5e6
commit
e7cadd90b2
@ -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);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user