@@ -727,7 +727,6 @@ size_t ShenandoahRegionChunkIterator::calc_regular_group_size() {
727727 // half of the remaining heap, the third processes half of what remains and so on. The smallest chunk size
728728 // is represented by _smallest_chunk_size_words. We do not divide work any smaller than this.
729729 //
730-
731730 size_t group_size = _heap->num_regions () / 2 ;
732731 return group_size;
733732}
@@ -773,6 +772,7 @@ size_t ShenandoahRegionChunkIterator::calc_num_groups() {
773772 // Any remaining regions will be treated as if they are part of the most recently created group. This group will
774773 // have more than _regular_group_size chunks within it.
775774 }
775+ assert (num_groups <= _maximum_groups, " Cannot have more than %zu groups" , _maximum_groups);
776776 return num_groups;
777777}
778778
@@ -784,21 +784,31 @@ size_t ShenandoahRegionChunkIterator::calc_total_chunks() {
784784 size_t current_group_span = _first_group_chunk_size_b4_rebalance * _regular_group_size;
785785 size_t smallest_group_span = smallest_chunk_size_words () * _regular_group_size;
786786
787- // The first group gets special handling because the first chunk size can be no larger than _largest_chunk_size_words
787+ // The first group gets special handling because the first chunk size can be no larger than _maximum_chunk_size_words
788788 if (region_size_words > _maximum_chunk_size_words) {
789789 // In the case that we shrink the first group's chunk size, certain other groups will also be subsumed within the first group
790790 size_t effective_chunk_size = _first_group_chunk_size_b4_rebalance;
791+ uint coalesced_groups = 0 ;
791792 while (effective_chunk_size >= _maximum_chunk_size_words) {
793+ // Each iteration of this loop subsumes one original group into a new rebalanced initial group.
792794 num_chunks += current_group_span / _maximum_chunk_size_words;
793795 unspanned_heap_size -= current_group_span;
794796 effective_chunk_size /= 2 ;
795797 current_group_span /= 2 ;
798+ coalesced_groups++;
796799 }
800+ assert (effective_chunk_size * 2 == _maximum_chunk_size_words,
801+ " We assume _first_group_chunk_size_b4_rebalance is _maximum_chunk_size_words * a power of two" );
802+ _largest_chunk_size_words = _maximum_chunk_size_words;
803+ _adjusted_num_groups = _num_groups - (coalesced_groups - 1 );
797804 } else {
798805 num_chunks = _regular_group_size;
799806 unspanned_heap_size -= current_group_span;
807+ _largest_chunk_size_words = current_group_span / num_chunks;
808+ _adjusted_num_groups = _num_groups;
800809 current_group_span /= 2 ;
801810 }
811+
802812 size_t spanned_groups = 1 ;
803813 while (unspanned_heap_size > 0 ) {
804814 if (current_group_span <= unspanned_heap_size) {
@@ -856,11 +866,12 @@ ShenandoahRegionChunkIterator::ShenandoahRegionChunkIterator(ShenandoahHeap* hea
856866 size_t expected_chunk_size_words = _clusters_in_smallest_chunk * CardTable::card_size_in_words () * ShenandoahCardCluster::CardsPerCluster;
857867 assert (smallest_chunk_size_words () == expected_chunk_size_words, " _smallest_chunk_size (%zu) is not valid because it does not equal (%zu)" ,
858868 smallest_chunk_size_words (), expected_chunk_size_words);
859- #endif
860869 assert (_num_groups <= _maximum_groups,
861870 " The number of remembered set scanning groups must be less than or equal to maximum groups" );
862- assert (smallest_chunk_size_words () << (_maximum_groups - 1 ) == _maximum_chunk_size_words,
863- " Maximum number of groups needs to span maximum chunk size to smallest chunk size" );
871+ assert (smallest_chunk_size_words () << (_adjusted_num_groups - 1 ) == _largest_chunk_size_words,
872+ " The number of groups (%zu) needs to span smallest chunk size (%zu) to largest chunk size (%zu)" ,
873+ _adjusted_num_groups, smallest_chunk_size_words (), _largest_chunk_size_words);
874+ #endif
864875
865876 size_t words_in_region = ShenandoahHeapRegion::region_size_words ();
866877 _region_index[0 ] = 0 ;
@@ -883,7 +894,7 @@ ShenandoahRegionChunkIterator::ShenandoahRegionChunkIterator(ShenandoahHeap* hea
883894 }
884895
885896 size_t previous_group_span = _group_entries[0 ] * _group_chunk_size[0 ];
886- for (size_t i = 1 ; i < _num_groups ; i++) {
897+ for (size_t i = 1 ; i < _adjusted_num_groups ; i++) {
887898 _group_chunk_size[i] = _group_chunk_size[i-1 ] / 2 ;
888899 size_t chunks_in_group = _regular_group_size;
889900 size_t this_group_span = _group_chunk_size[i] * chunks_in_group;
@@ -893,19 +904,19 @@ ShenandoahRegionChunkIterator::ShenandoahRegionChunkIterator(ShenandoahHeap* hea
893904 _group_entries[i] = _group_entries[i-1 ] + _regular_group_size;
894905 previous_group_span = total_span_of_groups;
895906 }
896- if (_group_entries[_num_groups -1 ] < _total_chunks) {
897- assert ((_total_chunks - _group_entries[_num_groups -1 ]) * _group_chunk_size[_num_groups -1 ] + previous_group_span ==
907+ if (_group_entries[_adjusted_num_groups -1 ] < _total_chunks) {
908+ assert ((_total_chunks - _group_entries[_adjusted_num_groups -1 ]) * _group_chunk_size[_adjusted_num_groups -1 ] + previous_group_span ==
898909 heap->num_regions () * words_in_region, " Total region chunks (%zu"
899910 " ) do not span total heap regions (%zu)" , _total_chunks, _heap->num_regions ());
900- previous_group_span += (_total_chunks - _group_entries[_num_groups -1 ]) * _group_chunk_size[_num_groups -1 ];
901- _group_entries[_num_groups -1 ] = _total_chunks;
911+ previous_group_span += (_total_chunks - _group_entries[_adjusted_num_groups -1 ]) * _group_chunk_size[_adjusted_num_groups -1 ];
912+ _group_entries[_adjusted_num_groups -1 ] = _total_chunks;
902913 }
903914 assert (previous_group_span == heap->num_regions () * words_in_region, " Total region chunks (%zu"
904915 " ) do not span total heap regions (%zu): %zu does not equal %zu" ,
905916 _total_chunks, _heap->num_regions (), previous_group_span, heap->num_regions () * words_in_region);
906917
907918 // Not necessary, but keeps things tidy
908- for (size_t i = _num_groups ; i < _maximum_groups; i++) {
919+ for (size_t i = _adjusted_num_groups ; i < _maximum_groups; i++) {
909920 _region_index[i] = 0 ;
910921 _group_offset[i] = 0 ;
911922 _group_entries[i] = _group_entries[i-1 ];
0 commit comments