@@ -110,27 +110,25 @@ void ShenandoahCollectionSet::clear() {
110110}
111111
112112ShenandoahHeapRegion* 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() {
139137ShenandoahHeapRegion* 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 }
0 commit comments