diff -r 355f4f42dda5 -r 95a99e617f28 src/hotspot/share/opto/indexSet.hpp --- a/src/hotspot/share/opto/indexSet.hpp Thu Nov 14 10:55:46 2019 +0100 +++ b/src/hotspot/share/opto/indexSet.hpp Thu Nov 14 15:24:35 2019 +0100 @@ -190,6 +190,9 @@ // The number of elements in the set uint _count; + // The current upper limit of blocks that has been allocated and might be in use + uint _current_block_limit; + // Our top level array of bitvector segments BitBlock **_blocks; @@ -246,12 +249,13 @@ void clear() { _count = 0; - for (uint i = 0; i < _max_blocks; i++) { + for (uint i = 0; i < _current_block_limit; i++) { BitBlock *block = _blocks[i]; if (block != &_empty_block) { free_block(i); } } + _current_block_limit = 0; } uint count() const { return _count; } @@ -380,18 +384,18 @@ // The index of the next word we will inspect uint _next_word; - // A pointer to the contents of the current block - uint32_t *_words; - // The index of the next block we will inspect uint _next_block; + // The number of blocks in the set + uint _max_blocks; + + // A pointer to the contents of the current block + uint32_t *_words; + // A pointer to the blocks in our set IndexSet::BitBlock **_blocks; - // The number of blocks in the set - uint _max_blocks; - // If the iterator was created from a non-const set, we replace // non-canonical empty blocks with the _empty_block pointer. If // _set is NULL, we do no replacement. @@ -405,22 +409,64 @@ // If an iterator is built from a constant set then empty blocks // are not canonicalized. - IndexSetIterator(IndexSet *set); - IndexSetIterator(const IndexSet *set); + IndexSetIterator(IndexSet *set) : + _current(0), + _value(0), + _next_word(IndexSet::words_per_block), + _next_block(0), + _max_blocks(set->is_empty() ? 0 : set->_current_block_limit), + _words(NULL), + _blocks(set->_blocks), + _set(set) { + #ifdef ASSERT + if (CollectIndexSetStatistics) { + set->tally_iteration_statistics(); + } + set->check_watch("traversed", set->count()); + #endif + } + + IndexSetIterator(const IndexSet *set) : + _current(0), + _value(0), + _next_word(IndexSet::words_per_block), + _next_block(0), + _max_blocks(set->is_empty() ? 0 : set->_current_block_limit), + _words(NULL), + _blocks(set->_blocks), + _set(NULL) + { + #ifdef ASSERT + if (CollectIndexSetStatistics) { + set->tally_iteration_statistics(); + } + // We don't call check_watch from here to avoid bad recursion. + // set->check_watch("traversed const", set->count()); + #endif + } + + // Return the next element of the set. + uint next_value() { + uint current = _current; + assert(current != 0, "sanity"); + uint advance = count_trailing_zeros(current); + assert(((current >> advance) & 0x1) == 1, "sanity"); + _current = (current >> advance) - 1; + _value += advance; + return _value; + } // Return the next element of the set. Return 0 when done. uint next() { - uint current = _current; - if (current != 0) { - uint advance = count_trailing_zeros(current); - assert(((current >> advance) & 0x1) == 1, "sanity"); - _current = (current >> advance) - 1; - _value += advance; - return _value; + if (_current != 0) { + return next_value(); + } else if (_next_word < IndexSet::words_per_block || _next_block < _max_blocks) { + return advance_and_next(); } else { - return advance_and_next(); + return 0; } } + }; #endif // SHARE_OPTO_INDEXSET_HPP