# HG changeset patch # User shade # Date 1549464786 -3600 # Wed Feb 06 15:53:06 2019 +0100 # Node ID 439cc5e6495bc88f5b0373c35f006cedaa200206 # Parent 58ffe5f227a6f69874792bf0fa7457d86b938b09 8211926: Catastrophic size_t underflow in BitMap::*_large methods Reviewed-by: kbarrett, stuefe diff --git a/src/share/vm/utilities/bitMap.cpp b/src/share/vm/utilities/bitMap.cpp --- a/src/share/vm/utilities/bitMap.cpp +++ b/src/share/vm/utilities/bitMap.cpp @@ -154,14 +154,24 @@ } } +bool BitMap::is_small_range_of_words(idx_t beg_full_word, idx_t end_full_word) { + // There is little point to call large version on small ranges. + // Need to check carefully, keeping potential idx_t underflow in mind. + // The threshold should be at least one word. + STATIC_ASSERT(small_range_words >= 1); + return (beg_full_word + small_range_words >= end_full_word); +} + void BitMap::set_large_range(idx_t beg, idx_t end) { verify_range(beg, end); idx_t beg_full_word = word_index_round_up(beg); idx_t end_full_word = word_index(end); - assert(end_full_word - beg_full_word >= 32, - "the range must include at least 32 bytes"); + if (is_small_range_of_words(beg_full_word, end_full_word)) { + set_range(beg, end); + return; + } // The range includes at least one full word. set_range_within_word(beg, bit_index(beg_full_word)); @@ -175,8 +185,10 @@ idx_t beg_full_word = word_index_round_up(beg); idx_t end_full_word = word_index(end); - assert(end_full_word - beg_full_word >= 32, - "the range must include at least 32 bytes"); + if (is_small_range_of_words(beg_full_word, end_full_word)) { + clear_range(beg, end); + return; + } // The range includes at least one full word. clear_range_within_word(beg, bit_index(beg_full_word)); @@ -264,8 +276,10 @@ idx_t beg_full_word = word_index_round_up(beg); idx_t end_full_word = word_index(end); - assert(end_full_word - beg_full_word >= 32, - "the range must include at least 32 bytes"); + if (is_small_range_of_words(beg_full_word, end_full_word)) { + par_at_put_range(beg, end, value); + return; + } // The range includes at least one full word. par_put_range_within_word(beg, bit_index(beg_full_word), value); diff --git a/src/share/vm/utilities/bitMap.hpp b/src/share/vm/utilities/bitMap.hpp --- a/src/share/vm/utilities/bitMap.hpp +++ b/src/share/vm/utilities/bitMap.hpp @@ -56,6 +56,10 @@ // the bitmap appropriately if needed using factor-of-two expansion. void at_put_grow(idx_t index, bool value); + // Threshold for performing small range operation, even when large range + // operation was requested. Measured in words. + static const size_t small_range_words = 32; + protected: // Return the position of bit within the word that contains it (e.g., if // bitmap words are 32 bits, return a number 0 <= n <= 31). @@ -97,6 +101,8 @@ void set_large_range_of_words (idx_t beg, idx_t end); void clear_large_range_of_words (idx_t beg, idx_t end); + static bool is_small_range_of_words(idx_t beg_full_word, idx_t end_full_word); + // The index of the first full word in a range. idx_t word_index_round_up(idx_t bit) const; diff --git a/src/share/vm/utilities/bitMap.inline.hpp b/src/share/vm/utilities/bitMap.inline.hpp --- a/src/share/vm/utilities/bitMap.inline.hpp +++ b/src/share/vm/utilities/bitMap.inline.hpp @@ -321,10 +321,12 @@ } inline void BitMap::set_large_range_of_words(idx_t beg, idx_t end) { + assert(beg <= end, "underflow"); memset(_map + beg, ~(unsigned char)0, (end - beg) * sizeof(uintptr_t)); } inline void BitMap::clear_large_range_of_words(idx_t beg, idx_t end) { + assert(beg <= end, "underflow"); memset(_map + beg, 0, (end - beg) * sizeof(uintptr_t)); }