# HG changeset patch # User tschatzl # Date 1397638558 -7200 # Node ID bd1a2ee20760fbe73a836355bce2750ab1195b04 # Parent 7e71ac14ec063ac373fb92418a61a8e6afb6da65 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 diff -r 7e71ac14ec06 -r bd1a2ee20760 hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Wed Apr 16 10:55:26 2014 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Wed Apr 16 10:55:58 2014 +0200 @@ -1048,20 +1048,16 @@ return _code_roots.mem_size(); } -//-------------------- Iteration -------------------- - HeapRegionRemSetIterator:: HeapRegionRemSetIterator(HeapRegionRemSet* hrrs) : _hrrs(hrrs), _g1h(G1CollectedHeap::heap()), _coarse_map(&hrrs->_other_regions._coarse_map), - _fine_grain_regions(hrrs->_other_regions._fine_grain_regions), _bosa(hrrs->bosa()), _is(Sparse), // Set these values so that we increment to the first region. _coarse_cur_region_index(-1), _coarse_cur_region_cur_card(HeapRegion::CardsPerRegion-1), - _cur_region_cur_card(0), - _fine_array_index(-1), + _cur_card_in_prt(HeapRegion::CardsPerRegion), _fine_cur_prt(NULL), _n_yielded_coarse(0), _n_yielded_fine(0), @@ -1093,58 +1089,59 @@ return true; } -void HeapRegionRemSetIterator::fine_find_next_non_null_prt() { - // Otherwise, find the next bucket list in the array. - _fine_array_index++; - while (_fine_array_index < (int) OtherRegionsTable::_max_fine_entries) { - _fine_cur_prt = _fine_grain_regions[_fine_array_index]; - if (_fine_cur_prt != NULL) return; - else _fine_array_index++; - } - assert(_fine_cur_prt == NULL, "Loop post"); -} - bool HeapRegionRemSetIterator::fine_has_next(size_t& card_index) { if (fine_has_next()) { - _cur_region_cur_card = - _fine_cur_prt->_bm.get_next_one_offset(_cur_region_cur_card + 1); + _cur_card_in_prt = + _fine_cur_prt->_bm.get_next_one_offset(_cur_card_in_prt + 1); } - while (!fine_has_next()) { - if (_cur_region_cur_card == (size_t) HeapRegion::CardsPerRegion) { - _cur_region_cur_card = 0; - _fine_cur_prt = _fine_cur_prt->collision_list_next(); + if (_cur_card_in_prt == HeapRegion::CardsPerRegion) { + // _fine_cur_prt may still be NULL in case if there are not PRTs at all for + // the remembered set. + if (_fine_cur_prt == NULL || _fine_cur_prt->next() == NULL) { + return false; } - if (_fine_cur_prt == NULL) { - fine_find_next_non_null_prt(); - if (_fine_cur_prt == NULL) return false; - } - assert(_fine_cur_prt != NULL && _cur_region_cur_card == 0, - "inv."); - HeapWord* r_bot = - _fine_cur_prt->hr()->bottom(); - _cur_region_card_offset = _bosa->index_for(r_bot); - _cur_region_cur_card = _fine_cur_prt->_bm.get_next_one_offset(0); + PerRegionTable* next_prt = _fine_cur_prt->next(); + switch_to_prt(next_prt); + _cur_card_in_prt = _fine_cur_prt->_bm.get_next_one_offset(_cur_card_in_prt + 1); } - assert(fine_has_next(), "Or else we exited the loop via the return."); - card_index = _cur_region_card_offset + _cur_region_cur_card; + + card_index = _cur_region_card_offset + _cur_card_in_prt; + guarantee(_cur_card_in_prt < HeapRegion::CardsPerRegion, + err_msg("Card index "SIZE_FORMAT" must be within the region", _cur_card_in_prt)); return true; } bool HeapRegionRemSetIterator::fine_has_next() { - return - _fine_cur_prt != NULL && - _cur_region_cur_card < HeapRegion::CardsPerRegion; + return _cur_card_in_prt != HeapRegion::CardsPerRegion; +} + +void HeapRegionRemSetIterator::switch_to_prt(PerRegionTable* prt) { + assert(prt != NULL, "Cannot switch to NULL prt"); + _fine_cur_prt = prt; + + HeapWord* r_bot = _fine_cur_prt->hr()->bottom(); + _cur_region_card_offset = _bosa->index_for(r_bot); + + // The bitmap scan for the PRT always scans from _cur_region_cur_card + 1. + // To avoid special-casing this start case, and not miss the first bitmap + // entry, initialize _cur_region_cur_card with -1 instead of 0. + _cur_card_in_prt = (size_t)-1; } bool HeapRegionRemSetIterator::has_next(size_t& card_index) { switch (_is) { - case Sparse: + case Sparse: { if (_sparse_iter.has_next(card_index)) { _n_yielded_sparse++; return true; } // Otherwise, deliberate fall-through _is = Fine; + PerRegionTable* initial_fine_prt = _hrrs->_other_regions._first_all_fine_prts; + if (initial_fine_prt != NULL) { + switch_to_prt(_hrrs->_other_regions._first_all_fine_prts); + } + } case Fine: if (fine_has_next(card_index)) { _n_yielded_fine++; diff -r 7e71ac14ec06 -r bd1a2ee20760 hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Wed Apr 16 10:55:26 2014 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Wed Apr 16 10:55:58 2014 +0200 @@ -428,26 +428,24 @@ }; class HeapRegionRemSetIterator : public StackObj { - - // The region RSet over which we're iterating. + private: + // The region RSet over which we are iterating. HeapRegionRemSet* _hrrs; // Local caching of HRRS fields. const BitMap* _coarse_map; - PerRegionTable** _fine_grain_regions; G1BlockOffsetSharedArray* _bosa; G1CollectedHeap* _g1h; - // The number yielded since initialization. + // The number of cards yielded since initialization. size_t _n_yielded_fine; size_t _n_yielded_coarse; size_t _n_yielded_sparse; - // Indicates what granularity of table that we're currently iterating over. + // Indicates what granularity of table that we are currently iterating over. // We start iterating over the sparse table, progress to the fine grain // table, and then finish with the coarse table. - // See HeapRegionRemSetIterator::has_next(). enum IterState { Sparse, Fine, @@ -455,38 +453,30 @@ }; IterState _is; - // In both kinds of iteration, heap offset of first card of current - // region. + // For both Coarse and Fine remembered set iteration this contains the + // first card number of the heap region we currently iterate over. size_t _cur_region_card_offset; - // Card offset within cur region. - size_t _cur_region_cur_card; - // Coarse table iteration fields: - - // Current region index; + // Current region index for the Coarse remembered set iteration. int _coarse_cur_region_index; size_t _coarse_cur_region_cur_card; bool coarse_has_next(size_t& card_index); - // Fine table iteration fields: - - // Index of bucket-list we're working on. - int _fine_array_index; + // The PRT we are currently iterating over. + PerRegionTable* _fine_cur_prt; + // Card offset within the current PRT. + size_t _cur_card_in_prt; - // Per Region Table we're doing within current bucket list. - PerRegionTable* _fine_cur_prt; - - /* SparsePRT::*/ SparsePRTIter _sparse_iter; - - void fine_find_next_non_null_prt(); - + // Update internal variables when switching to the given PRT. + void switch_to_prt(PerRegionTable* prt); bool fine_has_next(); bool fine_has_next(size_t& card_index); -public: - // We require an iterator to be initialized before use, so the - // constructor does little. + // The Sparse remembered set iterator. + SparsePRTIter _sparse_iter; + + public: HeapRegionRemSetIterator(HeapRegionRemSet* hrrs); // If there remains one or more cards to be yielded, returns true and