Mon, 21 Jul 2014 09:40:19 +0200
8037344: Use the "next" field to iterate over fine remembered instead of using the hash table
Summary: After changes to the PerRegionTable where all these PRTs are linked together in an additional field, simplify iterating over all PRTs by using these links instead of walki
Reviewed-by: mgerdin, jwilhelm, brutisso
1.1 --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Mon Jul 21 09:40:19 2014 +0200 1.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Mon Jul 21 09:40:19 2014 +0200 1.3 @@ -1048,20 +1048,16 @@ 1.4 return _code_roots.mem_size(); 1.5 } 1.6 1.7 -//-------------------- Iteration -------------------- 1.8 - 1.9 HeapRegionRemSetIterator:: HeapRegionRemSetIterator(HeapRegionRemSet* hrrs) : 1.10 _hrrs(hrrs), 1.11 _g1h(G1CollectedHeap::heap()), 1.12 _coarse_map(&hrrs->_other_regions._coarse_map), 1.13 - _fine_grain_regions(hrrs->_other_regions._fine_grain_regions), 1.14 _bosa(hrrs->bosa()), 1.15 _is(Sparse), 1.16 // Set these values so that we increment to the first region. 1.17 _coarse_cur_region_index(-1), 1.18 _coarse_cur_region_cur_card(HeapRegion::CardsPerRegion-1), 1.19 - _cur_region_cur_card(0), 1.20 - _fine_array_index(-1), 1.21 + _cur_card_in_prt(HeapRegion::CardsPerRegion), 1.22 _fine_cur_prt(NULL), 1.23 _n_yielded_coarse(0), 1.24 _n_yielded_fine(0), 1.25 @@ -1093,58 +1089,59 @@ 1.26 return true; 1.27 } 1.28 1.29 -void HeapRegionRemSetIterator::fine_find_next_non_null_prt() { 1.30 - // Otherwise, find the next bucket list in the array. 1.31 - _fine_array_index++; 1.32 - while (_fine_array_index < (int) OtherRegionsTable::_max_fine_entries) { 1.33 - _fine_cur_prt = _fine_grain_regions[_fine_array_index]; 1.34 - if (_fine_cur_prt != NULL) return; 1.35 - else _fine_array_index++; 1.36 - } 1.37 - assert(_fine_cur_prt == NULL, "Loop post"); 1.38 -} 1.39 - 1.40 bool HeapRegionRemSetIterator::fine_has_next(size_t& card_index) { 1.41 if (fine_has_next()) { 1.42 - _cur_region_cur_card = 1.43 - _fine_cur_prt->_bm.get_next_one_offset(_cur_region_cur_card + 1); 1.44 + _cur_card_in_prt = 1.45 + _fine_cur_prt->_bm.get_next_one_offset(_cur_card_in_prt + 1); 1.46 } 1.47 - while (!fine_has_next()) { 1.48 - if (_cur_region_cur_card == (size_t) HeapRegion::CardsPerRegion) { 1.49 - _cur_region_cur_card = 0; 1.50 - _fine_cur_prt = _fine_cur_prt->collision_list_next(); 1.51 + if (_cur_card_in_prt == HeapRegion::CardsPerRegion) { 1.52 + // _fine_cur_prt may still be NULL in case if there are not PRTs at all for 1.53 + // the remembered set. 1.54 + if (_fine_cur_prt == NULL || _fine_cur_prt->next() == NULL) { 1.55 + return false; 1.56 } 1.57 - if (_fine_cur_prt == NULL) { 1.58 - fine_find_next_non_null_prt(); 1.59 - if (_fine_cur_prt == NULL) return false; 1.60 - } 1.61 - assert(_fine_cur_prt != NULL && _cur_region_cur_card == 0, 1.62 - "inv."); 1.63 - HeapWord* r_bot = 1.64 - _fine_cur_prt->hr()->bottom(); 1.65 - _cur_region_card_offset = _bosa->index_for(r_bot); 1.66 - _cur_region_cur_card = _fine_cur_prt->_bm.get_next_one_offset(0); 1.67 + PerRegionTable* next_prt = _fine_cur_prt->next(); 1.68 + switch_to_prt(next_prt); 1.69 + _cur_card_in_prt = _fine_cur_prt->_bm.get_next_one_offset(_cur_card_in_prt + 1); 1.70 } 1.71 - assert(fine_has_next(), "Or else we exited the loop via the return."); 1.72 - card_index = _cur_region_card_offset + _cur_region_cur_card; 1.73 + 1.74 + card_index = _cur_region_card_offset + _cur_card_in_prt; 1.75 + guarantee(_cur_card_in_prt < HeapRegion::CardsPerRegion, 1.76 + err_msg("Card index "SIZE_FORMAT" must be within the region", _cur_card_in_prt)); 1.77 return true; 1.78 } 1.79 1.80 bool HeapRegionRemSetIterator::fine_has_next() { 1.81 - return 1.82 - _fine_cur_prt != NULL && 1.83 - _cur_region_cur_card < HeapRegion::CardsPerRegion; 1.84 + return _cur_card_in_prt != HeapRegion::CardsPerRegion; 1.85 +} 1.86 + 1.87 +void HeapRegionRemSetIterator::switch_to_prt(PerRegionTable* prt) { 1.88 + assert(prt != NULL, "Cannot switch to NULL prt"); 1.89 + _fine_cur_prt = prt; 1.90 + 1.91 + HeapWord* r_bot = _fine_cur_prt->hr()->bottom(); 1.92 + _cur_region_card_offset = _bosa->index_for(r_bot); 1.93 + 1.94 + // The bitmap scan for the PRT always scans from _cur_region_cur_card + 1. 1.95 + // To avoid special-casing this start case, and not miss the first bitmap 1.96 + // entry, initialize _cur_region_cur_card with -1 instead of 0. 1.97 + _cur_card_in_prt = (size_t)-1; 1.98 } 1.99 1.100 bool HeapRegionRemSetIterator::has_next(size_t& card_index) { 1.101 switch (_is) { 1.102 - case Sparse: 1.103 + case Sparse: { 1.104 if (_sparse_iter.has_next(card_index)) { 1.105 _n_yielded_sparse++; 1.106 return true; 1.107 } 1.108 // Otherwise, deliberate fall-through 1.109 _is = Fine; 1.110 + PerRegionTable* initial_fine_prt = _hrrs->_other_regions._first_all_fine_prts; 1.111 + if (initial_fine_prt != NULL) { 1.112 + switch_to_prt(_hrrs->_other_regions._first_all_fine_prts); 1.113 + } 1.114 + } 1.115 case Fine: 1.116 if (fine_has_next(card_index)) { 1.117 _n_yielded_fine++;
2.1 --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Mon Jul 21 09:40:19 2014 +0200 2.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Mon Jul 21 09:40:19 2014 +0200 2.3 @@ -432,26 +432,24 @@ 2.4 }; 2.5 2.6 class HeapRegionRemSetIterator : public StackObj { 2.7 - 2.8 - // The region RSet over which we're iterating. 2.9 + private: 2.10 + // The region RSet over which we are iterating. 2.11 HeapRegionRemSet* _hrrs; 2.12 2.13 // Local caching of HRRS fields. 2.14 const BitMap* _coarse_map; 2.15 - PerRegionTable** _fine_grain_regions; 2.16 2.17 G1BlockOffsetSharedArray* _bosa; 2.18 G1CollectedHeap* _g1h; 2.19 2.20 - // The number yielded since initialization. 2.21 + // The number of cards yielded since initialization. 2.22 size_t _n_yielded_fine; 2.23 size_t _n_yielded_coarse; 2.24 size_t _n_yielded_sparse; 2.25 2.26 - // Indicates what granularity of table that we're currently iterating over. 2.27 + // Indicates what granularity of table that we are currently iterating over. 2.28 // We start iterating over the sparse table, progress to the fine grain 2.29 // table, and then finish with the coarse table. 2.30 - // See HeapRegionRemSetIterator::has_next(). 2.31 enum IterState { 2.32 Sparse, 2.33 Fine, 2.34 @@ -459,38 +457,30 @@ 2.35 }; 2.36 IterState _is; 2.37 2.38 - // In both kinds of iteration, heap offset of first card of current 2.39 - // region. 2.40 + // For both Coarse and Fine remembered set iteration this contains the 2.41 + // first card number of the heap region we currently iterate over. 2.42 size_t _cur_region_card_offset; 2.43 - // Card offset within cur region. 2.44 - size_t _cur_region_cur_card; 2.45 2.46 - // Coarse table iteration fields: 2.47 - 2.48 - // Current region index; 2.49 + // Current region index for the Coarse remembered set iteration. 2.50 int _coarse_cur_region_index; 2.51 size_t _coarse_cur_region_cur_card; 2.52 2.53 bool coarse_has_next(size_t& card_index); 2.54 2.55 - // Fine table iteration fields: 2.56 + // The PRT we are currently iterating over. 2.57 + PerRegionTable* _fine_cur_prt; 2.58 + // Card offset within the current PRT. 2.59 + size_t _cur_card_in_prt; 2.60 2.61 - // Index of bucket-list we're working on. 2.62 - int _fine_array_index; 2.63 - 2.64 - // Per Region Table we're doing within current bucket list. 2.65 - PerRegionTable* _fine_cur_prt; 2.66 - 2.67 - /* SparsePRT::*/ SparsePRTIter _sparse_iter; 2.68 - 2.69 - void fine_find_next_non_null_prt(); 2.70 - 2.71 + // Update internal variables when switching to the given PRT. 2.72 + void switch_to_prt(PerRegionTable* prt); 2.73 bool fine_has_next(); 2.74 bool fine_has_next(size_t& card_index); 2.75 2.76 -public: 2.77 - // We require an iterator to be initialized before use, so the 2.78 - // constructor does little. 2.79 + // The Sparse remembered set iterator. 2.80 + SparsePRTIter _sparse_iter; 2.81 + 2.82 + public: 2.83 HeapRegionRemSetIterator(HeapRegionRemSet* hrrs); 2.84 2.85 // If there remains one or more cards to be yielded, returns true and