Skip to content

Commit fd098e7

Browse files
committed
8261838: Shenandoah: reconsider heap region iterators memory ordering
Reviewed-by: rkennke
1 parent f94a845 commit fd098e7

File tree

4 files changed

+21
-22
lines changed

4 files changed

+21
-22
lines changed

src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -110,27 +110,25 @@ void ShenandoahCollectionSet::clear() {
110110
}
111111

112112
ShenandoahHeapRegion* ShenandoahCollectionSet::claim_next() {
113-
size_t num_regions = _heap->num_regions();
114-
if (_current_index >= (jint)num_regions) {
115-
return NULL;
116-
}
113+
// This code is optimized for the case when collection set contains only
114+
// a few regions. In this case, it is more constructive to check for is_in
115+
// before hitting the (potentially contended) atomic index.
117116

118-
jint saved_current = _current_index;
119-
size_t index = (size_t)saved_current;
117+
size_t max = _heap->num_regions();
118+
size_t old = Atomic::load(&_current_index);
120119

121-
while(index < num_regions) {
120+
for (size_t index = old; index < max; index++) {
122121
if (is_in(index)) {
123-
jint cur = Atomic::cmpxchg(&_current_index, saved_current, (jint)(index + 1));
124-
assert(cur >= (jint)saved_current, "Must move forward");
125-
if (cur == saved_current) {
126-
assert(is_in(index), "Invariant");
122+
size_t cur = Atomic::cmpxchg(&_current_index, old, index + 1, memory_order_relaxed);
123+
assert(cur >= old, "Always move forward");
124+
if (cur == old) {
125+
// Successfully moved the claim index, this is our region.
127126
return _heap->get_region(index);
128127
} else {
129-
index = (size_t)cur;
130-
saved_current = cur;
128+
// Somebody else moved the claim index, restart from there.
129+
index = cur - 1; // adjust for loop post-increment
130+
old = cur;
131131
}
132-
} else {
133-
index ++;
134132
}
135133
}
136134
return NULL;
@@ -139,10 +137,11 @@ ShenandoahHeapRegion* ShenandoahCollectionSet::claim_next() {
139137
ShenandoahHeapRegion* ShenandoahCollectionSet::next() {
140138
assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
141139
assert(Thread::current()->is_VM_thread(), "Must be VMThread");
142-
size_t num_regions = _heap->num_regions();
143-
for (size_t index = (size_t)_current_index; index < num_regions; index ++) {
140+
141+
size_t max = _heap->num_regions();
142+
for (size_t index = _current_index; index < max; index++) {
144143
if (is_in(index)) {
145-
_current_index = (jint)(index + 1);
144+
_current_index = index + 1;
146145
return _heap->get_region(index);
147146
}
148147
}

src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class ShenandoahCollectionSet : public CHeapObj<mtGC> {
4747
size_t _region_count;
4848

4949
shenandoah_padding(0);
50-
volatile jint _current_index;
50+
volatile size_t _current_index;
5151
shenandoah_padding(1);
5252

5353
public:

src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,8 +1497,8 @@ class ShenandoahParallelHeapRegionTask : public AbstractGangTask {
14971497
size_t stride = ShenandoahParallelRegionStride;
14981498

14991499
size_t max = _heap->num_regions();
1500-
while (_index < max) {
1501-
size_t cur = Atomic::fetch_and_add(&_index, stride);
1500+
while (Atomic::load(&_index) < max) {
1501+
size_t cur = Atomic::fetch_and_add(&_index, stride, memory_order_relaxed);
15021502
size_t start = cur;
15031503
size_t end = MIN2(cur + stride, max);
15041504
if (start >= max) break;

src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ inline ShenandoahHeap* ShenandoahHeap::heap() {
5454
}
5555

5656
inline ShenandoahHeapRegion* ShenandoahRegionIterator::next() {
57-
size_t new_index = Atomic::add(&_index, (size_t) 1);
57+
size_t new_index = Atomic::add(&_index, (size_t) 1, memory_order_relaxed);
5858
// get_region() provides the bounds-check and returns NULL on OOB.
5959
return _heap->get_region(new_index - 1);
6060
}

0 commit comments

Comments
 (0)