--- old/src/hotspot/share/gc/parallel/parMarkBitMap.cpp 2019-11-28 16:53:07.743289558 -0500 +++ new/src/hotspot/share/gc/parallel/parMarkBitMap.cpp 2019-11-28 16:53:07.515277311 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ const idx_t bits = bits_required(covered_region); // The bits will be divided evenly between two bitmaps; each of them should be // an integral number of words. - assert(bits % (BitsPerWord * 2) == 0, "region size unaligned"); + assert(is_aligned(bits, (BitsPerWord * 2)), "region size unaligned"); const size_t words = bits / BitsPerWord; const size_t raw_bytes = words * sizeof(idx_t); @@ -118,7 +118,7 @@ // The bitmap routines require the right boundary to be word-aligned. const idx_t end_bit = addr_to_bit((HeapWord*)end_obj); - const idx_t range_end = BitMap::word_align_up(end_bit); + const idx_t range_end = align_range_end(end_bit); idx_t beg_bit = find_obj_beg(addr_to_bit(beg_addr), range_end); while (beg_bit < end_bit) { @@ -177,7 +177,7 @@ assert(range_beg <= range_end, "live range invalid"); // The bitmap routines require the right boundary to be word-aligned. - const idx_t search_end = BitMap::word_align_up(range_end); + const idx_t search_end = align_range_end(range_end); idx_t cur_beg = find_obj_beg(range_beg, search_end); while (cur_beg < range_end) { @@ -216,8 +216,8 @@ assert(range_end <= dead_range_end, "dead range invalid"); // The bitmap routines require the right boundary to be word-aligned. - const idx_t live_search_end = BitMap::word_align_up(range_end); - const idx_t dead_search_end = BitMap::word_align_up(dead_range_end); + const idx_t live_search_end = align_range_end(range_end); + const idx_t dead_search_end = align_range_end(dead_range_end); idx_t cur_beg = range_beg; if (range_beg < range_end && is_unmarked(range_beg)) { --- old/src/hotspot/share/gc/parallel/parMarkBitMap.hpp 2019-11-28 16:53:08.719341986 -0500 +++ new/src/hotspot/share/gc/parallel/parMarkBitMap.hpp 2019-11-28 16:53:08.459328020 -0500 @@ -138,8 +138,12 @@ inline idx_t addr_to_bit(HeapWord* addr) const; inline HeapWord* bit_to_addr(idx_t bit) const; + // Return word-aligned up range_end, which must not be greater than size(). + inline idx_t align_range_end(idx_t range_end) const; + // Return the bit index of the first marked object that begins (or ends, // respectively) in the range [beg, end). If no object is found, return end. + // end must be word-aligned. inline idx_t find_obj_beg(idx_t beg, idx_t end) const; inline idx_t find_obj_end(idx_t beg, idx_t end) const; --- old/src/hotspot/share/gc/parallel/parMarkBitMap.inline.hpp 2019-11-28 16:53:09.707395059 -0500 +++ new/src/hotspot/share/gc/parallel/parMarkBitMap.inline.hpp 2019-11-28 16:53:09.451381307 -0500 @@ -26,6 +26,7 @@ #define SHARE_GC_PARALLEL_PARMARKBITMAP_INLINE_HPP #include "gc/parallel/parMarkBitMap.hpp" +#include "utilities/align.hpp" #include "utilities/bitMap.inline.hpp" inline ParMarkBitMap::ParMarkBitMap(): @@ -146,7 +147,7 @@ return mark_obj((HeapWord*)obj, (size_t)size); } -inline BitMap::idx_t ParMarkBitMap::addr_to_bit(HeapWord* addr) const { +inline ParMarkBitMap::idx_t ParMarkBitMap::addr_to_bit(HeapWord* addr) const { DEBUG_ONLY(verify_addr(addr);) return words_to_bits(pointer_delta(addr, region_start())); } @@ -156,6 +157,12 @@ return region_start() + bits_to_words(bit); } +inline ParMarkBitMap::idx_t ParMarkBitMap::align_range_end(idx_t range_end) const { + // size is aligned, so if range_end <= size then so is aligned result. + assert(range_end <= size(), "range end out of range"); + return align_up(range_end, BitsPerWord); +} + inline ParMarkBitMap::idx_t ParMarkBitMap::find_obj_beg(idx_t beg, idx_t end) const { return _beg_bits.get_next_one_offset_aligned_right(beg, end); } @@ -167,7 +174,7 @@ inline HeapWord* ParMarkBitMap::find_obj_beg(HeapWord* beg, HeapWord* end) const { const idx_t beg_bit = addr_to_bit(beg); const idx_t end_bit = addr_to_bit(end); - const idx_t search_end = BitMap::word_align_up(end_bit); + const idx_t search_end = align_range_end(end_bit); const idx_t res_bit = MIN2(find_obj_beg(beg_bit, search_end), end_bit); return bit_to_addr(res_bit); } @@ -175,7 +182,7 @@ inline HeapWord* ParMarkBitMap::find_obj_end(HeapWord* beg, HeapWord* end) const { const idx_t beg_bit = addr_to_bit(beg); const idx_t end_bit = addr_to_bit(end); - const idx_t search_end = BitMap::word_align_up(end_bit); + const idx_t search_end = align_range_end(end_bit); const idx_t res_bit = MIN2(find_obj_end(beg_bit, search_end), end_bit); return bit_to_addr(res_bit); } --- old/src/hotspot/share/gc/parallel/psParallelCompact.cpp 2019-11-28 16:53:10.675447057 -0500 +++ new/src/hotspot/share/gc/parallel/psParallelCompact.cpp 2019-11-28 16:53:10.419433305 -0500 @@ -961,7 +961,7 @@ HeapWord* const max_top = MAX2(top, _space_info[id].new_top()); const idx_t beg_bit = _mark_bitmap.addr_to_bit(bot); - const idx_t end_bit = BitMap::word_align_up(_mark_bitmap.addr_to_bit(top)); + const idx_t end_bit = _mark_bitmap.align_range_end(_mark_bitmap.addr_to_bit(top)); _mark_bitmap.clear_range(beg_bit, end_bit); const size_t beg_region = _summary_data.addr_to_region_idx(bot); @@ -2849,7 +2849,7 @@ ParMarkBitMap* m = mark_bitmap(); idx_t bits_to_skip = m->words_to_bits(count); idx_t cur_beg = m->addr_to_bit(beg); - const idx_t search_end = BitMap::word_align_up(m->addr_to_bit(end)); + const idx_t search_end = m->align_range_end(m->addr_to_bit(end)); do { cur_beg = m->find_obj_beg(cur_beg, search_end); --- old/src/hotspot/share/utilities/bitMap.cpp 2019-11-28 16:53:11.675500774 -0500 +++ new/src/hotspot/share/utilities/bitMap.cpp 2019-11-28 16:53:11.423487237 -0500 @@ -174,14 +174,27 @@ } #ifdef ASSERT -void BitMap::verify_index(idx_t index) const { - assert(index < _size, "BitMap index out of bounds"); +void BitMap::verify_size(idx_t size_in_bits) { + assert(size_in_bits <= max_size_in_bits(), + "out of bounds: " SIZE_FORMAT, size_in_bits); } -void BitMap::verify_range(idx_t beg_index, idx_t end_index) const { - assert(beg_index <= end_index, "BitMap range error"); - // Note that [0,0) and [size,size) are both valid ranges. - if (end_index != _size) verify_index(end_index); +void BitMap::verify_index(idx_t bit) const { + assert(bit < _size, + "BitMap index out of bounds: " SIZE_FORMAT " >= " SIZE_FORMAT, + bit, _size); +} + +void BitMap::verify_limit(idx_t bit) const { + assert(bit <= _size, + "BitMap limit out of bounds: " SIZE_FORMAT " > " SIZE_FORMAT, + bit, _size); +} + +void BitMap::verify_range(idx_t beg, idx_t end) const { + assert(beg <= end, + "BitMap range error: " SIZE_FORMAT " > " SIZE_FORMAT, beg, end); + verify_limit(end); } #endif // #ifdef ASSERT @@ -228,8 +241,8 @@ void BitMap::set_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); + idx_t beg_full_word = to_words_align_up(beg); + idx_t end_full_word = to_words_align_down(end); if (beg_full_word < end_full_word) { // The range includes at least one full word. @@ -247,8 +260,8 @@ void BitMap::clear_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); + idx_t beg_full_word = to_words_align_up(beg); + idx_t end_full_word = to_words_align_down(end); if (beg_full_word < end_full_word) { // The range includes at least one full word. @@ -265,17 +278,19 @@ 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. + // Need to check carefully, keeping potential idx_t over/underflow in mind, + // because beg_full_word > end_full_word can occur when beg and end are in + // the same word. // The threshold should be at least one word. STATIC_ASSERT(small_range_words >= 1); - return (beg_full_word + small_range_words >= end_full_word); + 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); + idx_t beg_full_word = to_words_align_up(beg); + idx_t end_full_word = to_words_align_down(end); if (is_small_range_of_words(beg_full_word, end_full_word)) { set_range(beg, end); @@ -291,8 +306,8 @@ void BitMap::clear_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); + idx_t beg_full_word = to_words_align_up(beg); + idx_t end_full_word = to_words_align_down(end); if (is_small_range_of_words(beg_full_word, end_full_word)) { clear_range(beg, end); @@ -343,8 +358,8 @@ void BitMap::par_at_put_range(idx_t beg, idx_t end, bool value) { verify_range(beg, end); - idx_t beg_full_word = word_index_round_up(beg); - idx_t end_full_word = word_index(end); + idx_t beg_full_word = to_words_align_up(beg); + idx_t end_full_word = to_words_align_down(end); if (beg_full_word < end_full_word) { // The range includes at least one full word. @@ -375,8 +390,8 @@ void BitMap::par_at_put_large_range(idx_t beg, idx_t end, bool value) { verify_range(beg, end); - idx_t beg_full_word = word_index_round_up(beg); - idx_t end_full_word = word_index(end); + idx_t beg_full_word = to_words_align_up(beg); + idx_t end_full_word = to_words_align_down(end); if (is_small_range_of_words(beg_full_word, end_full_word)) { par_at_put_range(beg, end, value); @@ -420,7 +435,7 @@ assert(size() == other.size(), "must have same size"); const bm_word_t* dest_map = map(); const bm_word_t* other_map = other.map(); - idx_t limit = word_index(size()); + idx_t limit = to_words_align_down(size()); for (idx_t index = 0; index < limit; ++index) { // false if other bitmap has bits set which are clear in this bitmap. if ((~dest_map[index] & other_map[index]) != 0) return false; @@ -435,7 +450,7 @@ assert(size() == other.size(), "must have same size"); const bm_word_t* dest_map = map(); const bm_word_t* other_map = other.map(); - idx_t limit = word_index(size()); + idx_t limit = to_words_align_down(size()); for (idx_t index = 0; index < limit; ++index) { if ((dest_map[index] & other_map[index]) != 0) return true; } @@ -448,7 +463,7 @@ assert(size() == other.size(), "must have same size"); bm_word_t* dest_map = map(); const bm_word_t* other_map = other.map(); - idx_t limit = word_index(size()); + idx_t limit = to_words_align_down(size()); for (idx_t index = 0; index < limit; ++index) { dest_map[index] |= other_map[index]; } @@ -463,7 +478,7 @@ assert(size() == other.size(), "must have same size"); bm_word_t* dest_map = map(); const bm_word_t* other_map = other.map(); - idx_t limit = word_index(size()); + idx_t limit = to_words_align_down(size()); for (idx_t index = 0; index < limit; ++index) { dest_map[index] &= ~other_map[index]; } @@ -478,7 +493,7 @@ assert(size() == other.size(), "must have same size"); bm_word_t* dest_map = map(); const bm_word_t* other_map = other.map(); - idx_t limit = word_index(size()); + idx_t limit = to_words_align_down(size()); for (idx_t index = 0; index < limit; ++index) { dest_map[index] &= other_map[index]; } @@ -494,7 +509,7 @@ bool changed = false; bm_word_t* dest_map = map(); const bm_word_t* other_map = other.map(); - idx_t limit = word_index(size()); + idx_t limit = to_words_align_down(size()); for (idx_t index = 0; index < limit; ++index) { bm_word_t orig = dest_map[index]; bm_word_t temp = orig | other_map[index]; @@ -516,7 +531,7 @@ bool changed = false; bm_word_t* dest_map = map(); const bm_word_t* other_map = other.map(); - idx_t limit = word_index(size()); + idx_t limit = to_words_align_down(size()); for (idx_t index = 0; index < limit; ++index) { bm_word_t orig = dest_map[index]; bm_word_t temp = orig & ~other_map[index]; @@ -538,7 +553,7 @@ bool changed = false; bm_word_t* dest_map = map(); const bm_word_t* other_map = other.map(); - idx_t limit = word_index(size()); + idx_t limit = to_words_align_down(size()); for (idx_t index = 0; index < limit; ++index) { bm_word_t orig = dest_map[index]; bm_word_t temp = orig & other_map[index]; @@ -559,7 +574,7 @@ assert(size() == other.size(), "must have same size"); bm_word_t* dest_map = map(); const bm_word_t* other_map = other.map(); - idx_t copy_words = word_index(size()); + idx_t copy_words = to_words_align_down(size()); Copy::disjoint_words((HeapWord*)other_map, (HeapWord*)dest_map, copy_words); idx_t rest = bit_in_word(size()); if (rest > 0) { @@ -573,7 +588,7 @@ assert(size() == other.size(), "must have same size"); const bm_word_t* dest_map = map(); const bm_word_t* other_map = other.map(); - idx_t limit = word_index(size()); + idx_t limit = to_words_align_down(size()); for (idx_t index = 0; index < limit; ++index) { if (dest_map[index] != other_map[index]) return false; } @@ -583,7 +598,7 @@ bool BitMap::is_full() const { const bm_word_t* words = map(); - idx_t limit = word_index(size()); + idx_t limit = to_words_align_down(size()); for (idx_t index = 0; index < limit; ++index) { if (~words[index] != 0) return false; } @@ -593,7 +608,7 @@ bool BitMap::is_empty() const { const bm_word_t* words = map(); - idx_t limit = word_index(size()); + idx_t limit = to_words_align_down(size()); for (idx_t index = 0; index < limit; ++index) { if (words[index] != 0) return false; } @@ -612,8 +627,8 @@ bool BitMap::iterate(BitMapClosure* blk, idx_t leftOffset, idx_t rightOffset) { verify_range(leftOffset, rightOffset); - idx_t startIndex = word_index(leftOffset); - idx_t endIndex = MIN2(word_index(rightOffset) + 1, size_in_words()); + idx_t startIndex = to_words_align_down(leftOffset); + idx_t endIndex = to_words_align_up(rightOffset); for (idx_t index = startIndex, offset = leftOffset; offset < rightOffset && index < endIndex; offset = (++index) << LogBitsPerWord) { --- old/src/hotspot/share/utilities/bitMap.hpp 2019-11-28 16:53:12.655553417 -0500 +++ new/src/hotspot/share/utilities/bitMap.hpp 2019-11-28 16:53:12.395539450 -0500 @@ -27,13 +27,12 @@ #include "memory/allocation.hpp" #include "runtime/atomic.hpp" -#include "utilities/align.hpp" // Forward decl; class BitMapClosure; // Operations for bitmaps represented as arrays of unsigned integers. -// Bit offsets are numbered from 0 to size-1. +// Bits are numbered from 0 to size-1. // The "abstract" base BitMap class. // @@ -50,8 +49,10 @@ public: typedef size_t idx_t; // Type used for bit and word indices. - typedef uintptr_t bm_word_t; // Element type of array that represents - // the bitmap. + typedef uintptr_t bm_word_t; // Element type of array that represents the + // bitmap, with BitsPerWord bits per element. + // If this were to fail, there are lots of places that would need repair. + STATIC_ASSERT((sizeof(bm_word_t) * BitsPerByte) == BitsPerWord); // Hints for range sizes. typedef enum { @@ -62,6 +63,35 @@ bm_word_t* _map; // First word in bitmap idx_t _size; // Size of bitmap (in bits) + // The maximum allowable size of a bitmap, in words or bits. + // Limit max_size_in_bits so aligning up to a word boundary never overflows. + static idx_t max_size_in_words() { return raw_to_words_align_down(~idx_t(0)); } + static idx_t max_size_in_bits() { return max_size_in_words() * BitsPerWord; } + + // Assumes relevant validity checking for bit has already been done. + static idx_t raw_to_words_align_up(idx_t bit) { + return raw_to_words_align_down(bit + (BitsPerWord - 1)); + } + + // Assumes relevant validity checking for bit has already been done. + static idx_t raw_to_words_align_down(idx_t bit) { + return bit >> LogBitsPerWord; + } + + // Word-aligns bit and converts it to a word offset. + // precondition: bit <= size() + idx_t to_words_align_up(idx_t bit) const { + verify_limit(bit); + return raw_to_words_align_up(bit); + } + + // Word-aligns bit and converts it to a word offset. + // precondition: bit <= size() + inline idx_t to_words_align_down(idx_t bit) const { + verify_limit(bit); + return raw_to_words_align_down(bit); + } + // Helper for get_next_{zero,one}_bit variants. // - flip designates whether searching for 1s or 0s. Must be one of // find_{zeros,ones}_flip. @@ -77,6 +107,8 @@ // operation was requested. Measured in words. static const size_t small_range_words = 32; + static bool is_small_range_of_words(idx_t beg_full_word, idx_t end_full_word); + 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). @@ -86,9 +118,6 @@ // containing the bit. static bm_word_t bit_mask(idx_t bit) { return (bm_word_t)1 << bit_in_word(bit); } - // Return the index of the word containing the specified bit. - static idx_t word_index(idx_t bit) { return bit >> LogBitsPerWord; } - // Return the bit number of the first bit in the specified word. static idx_t bit_index(idx_t word) { return word << LogBitsPerWord; } @@ -98,8 +127,12 @@ bm_word_t map(idx_t word) const { return _map[word]; } // Return a pointer to the word containing the specified bit. - bm_word_t* word_addr(idx_t bit) { return map() + word_index(bit); } - const bm_word_t* word_addr(idx_t bit) const { return map() + word_index(bit); } + bm_word_t* word_addr(idx_t bit) { + return map() + to_words_align_down(bit); + } + const bm_word_t* word_addr(idx_t bit) const { + return map() + to_words_align_down(bit); + } // Set a word to a specified value or to all ones; clear a word. void set_word (idx_t word, bm_word_t val) { _map[word] = val; } @@ -124,14 +157,16 @@ static void clear_range_of_words(bm_word_t* map, 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; - // Verification. - void verify_index(idx_t index) const NOT_DEBUG_RETURN; - void verify_range(idx_t beg_index, idx_t end_index) const NOT_DEBUG_RETURN; + + // Verify size_in_bits does not exceed max_size_in_bits(). + static void verify_size(idx_t size_in_bits) NOT_DEBUG_RETURN; + // Verify bit is less than size(). + void verify_index(idx_t bit) const NOT_DEBUG_RETURN; + // Verify bit is not greater than size(). + void verify_limit(idx_t bit) const NOT_DEBUG_RETURN; + // Verify [beg,end) is a valid range, e.g. beg <= end <= size(). + void verify_range(idx_t beg, idx_t end) const NOT_DEBUG_RETURN; // Statistics. static const idx_t* _pop_count_table; @@ -182,7 +217,9 @@ } // Protected constructor and destructor. - BitMap(bm_word_t* map, idx_t size_in_bits) : _map(map), _size(size_in_bits) {} + BitMap(bm_word_t* map, idx_t size_in_bits) : _map(map), _size(size_in_bits) { + verify_size(size_in_bits); + } ~BitMap() {} public: @@ -191,16 +228,13 @@ // Accessing static idx_t calc_size_in_words(size_t size_in_bits) { - return word_index(size_in_bits + BitsPerWord - 1); - } - - static idx_t calc_size_in_bytes(size_t size_in_bits) { - return calc_size_in_words(size_in_bits) * BytesPerWord; + verify_size(size_in_bits); + return raw_to_words_align_up(size_in_bits); } idx_t size() const { return _size; } idx_t size_in_words() const { return calc_size_in_words(size()); } - idx_t size_in_bytes() const { return calc_size_in_bytes(size()); } + idx_t size_in_bytes() const { return size_in_words() * BytesPerWord; } bool at(idx_t index) const { verify_index(index); @@ -210,18 +244,6 @@ // memory_order must be memory_order_relaxed or memory_order_acquire. bool par_at(idx_t index, atomic_memory_order memory_order = memory_order_acquire) const; - // Align bit index up or down to the next bitmap word boundary, or check - // alignment. - static idx_t word_align_up(idx_t bit) { - return align_up(bit, BitsPerWord); - } - static idx_t word_align_down(idx_t bit) { - return align_down(bit, BitsPerWord); - } - static bool is_word_aligned(idx_t bit) { - return word_align_up(bit) == bit; - } - // Set or clear the specified bit. inline void set_bit(idx_t bit); inline void clear_bit(idx_t bit); @@ -235,7 +257,7 @@ inline bool par_set_bit(idx_t bit, atomic_memory_order memory_order = memory_order_conservative); inline bool par_clear_bit(idx_t bit, atomic_memory_order memory_order = memory_order_conservative); - // Put the given value at the given offset. The parallel version + // Put the given value at the given index. The parallel version // will CAS the value into the bitmap and is quite a bit slower. // The parallel version also returns a value indicating if the // calling thread was the one that changed the value of the bit. @@ -454,7 +476,7 @@ public: // Callback when bit in map is set. Should normally return "true"; // return of false indicates that the bitmap iteration should terminate. - virtual bool do_bit(BitMap::idx_t offset) = 0; + virtual bool do_bit(BitMap::idx_t index) = 0; }; #endif // SHARE_UTILITIES_BITMAP_HPP --- old/src/hotspot/share/utilities/bitMap.inline.hpp 2019-11-28 16:53:13.655607134 -0500 +++ new/src/hotspot/share/utilities/bitMap.inline.hpp 2019-11-28 16:53:13.395593167 -0500 @@ -26,7 +26,7 @@ #define SHARE_UTILITIES_BITMAP_INLINE_HPP #include "runtime/atomic.hpp" -#include "runtime/orderAccess.hpp" +#include "utilities/align.hpp" #include "utilities/bitMap.hpp" #include "utilities/count_trailing_zeros.hpp" @@ -168,7 +168,7 @@ inline BitMap::idx_t BitMap::get_next_bit_impl(idx_t l_index, idx_t r_index) const { STATIC_ASSERT(flip == find_ones_flip || flip == find_zeros_flip); verify_range(l_index, r_index); - assert(!aligned_right || is_word_aligned(r_index), "r_index not aligned"); + assert(!aligned_right || is_aligned(r_index, BitsPerWord), "r_index not aligned"); // The first word often contains an interesting bit, either due to // density or because of features of the calling algorithm. So it's @@ -177,8 +177,8 @@ // first word is indeed interesting. // The benefit from aligned_right being true is relatively small. - // It saves a couple instructions in the setup for the word search - // loop. It also eliminates the range check on the final result. + // It saves an operation in the setup for the word search loop. + // It also eliminates the range check on the final result. // However, callers often have a comparison with r_index, and // inlining often allows the two comparisons to be combined; it is // important when !aligned_right that return paths either return @@ -189,7 +189,7 @@ if (l_index < r_index) { // Get the word containing l_index, and shift out low bits. - idx_t index = word_index(l_index); + idx_t index = to_words_align_down(l_index); bm_word_t cword = (map(index) ^ flip) >> bit_in_word(l_index); if ((cword & 1) != 0) { // The first bit is similarly often interesting. When it matters @@ -209,8 +209,8 @@ // Flipped and shifted first word is zero. Word search through // aligned up r_index for a non-zero flipped word. idx_t limit = aligned_right - ? word_index(r_index) - : (word_index(r_index - 1) + 1); // Align up, knowing r_index > 0. + ? to_words_align_down(r_index) // Miniscule savings when aligned. + : to_words_align_up(r_index); while (++index < limit) { cword = map(index) ^ flip; if (cword != 0) { @@ -249,7 +249,7 @@ inline BitMap::bm_word_t BitMap::inverted_bit_mask_for_range(idx_t beg, idx_t end) const { assert(end != 0, "does not work when end == 0"); - assert(beg == end || word_index(beg) == word_index(end - 1), + assert(beg == end || to_words_align_down(beg) == to_words_align_down(end - 1), "must be a single-word range"); bm_word_t mask = bit_mask(beg) - 1; // low (right) bits if (bit_in_word(end) != 0) { @@ -268,12 +268,6 @@ memset(_map + beg, 0, (end - beg) * sizeof(bm_word_t)); } -inline BitMap::idx_t BitMap::word_index_round_up(idx_t bit) const { - idx_t bit_rounded_up = bit + (BitsPerWord - 1); - // Check for integer arithmetic overflow. - return bit_rounded_up > bit ? word_index(bit_rounded_up) : size_in_words(); -} - inline bool BitMap2D::is_valid_index(idx_t slot_index, idx_t bit_within_slot_index) { verify_bit_within_slot_index(bit_within_slot_index); return (bit_index(slot_index, bit_within_slot_index) < size_in_bits()); --- old/test/hotspot/gtest/utilities/test_bitMap_setops.cpp 2019-11-28 16:53:14.651660636 -0500 +++ new/test/hotspot/gtest/utilities/test_bitMap_setops.cpp 2019-11-28 16:53:14.395646884 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,7 @@ */ #include "precompiled.hpp" +#include "utilities/align.hpp" #include "utilities/bitMap.inline.hpp" #include "utilities/copy.hpp" #include "utilities/debug.hpp" @@ -32,6 +33,10 @@ typedef BitMap::idx_t idx_t; typedef BitMap::bm_word_t bm_word_t; +inline idx_t word_align_down(idx_t bit) { + return align_down(bit, BitsPerWord); +} + class BitMapMemory { private: idx_t _words; @@ -147,7 +152,7 @@ // Check that a difference in the final partial word does count. { idx_t index = unaligned_size - 2; - ASSERT_LE(BitMap::word_align_down(unaligned_size), index); + ASSERT_LE(word_align_down(unaligned_size), index); WithBitClear wbc(y, index); EXPECT_FALSE(x.is_same(y)); @@ -261,7 +266,7 @@ // Check that a missing bit in the final partial word does count. { idx_t index = unaligned_size - 2; - ASSERT_LE(BitMap::word_align_down(unaligned_size), index); + ASSERT_LE(word_align_down(unaligned_size), index); WithBitClear wbc(x, index); EXPECT_FALSE(x.contains(y)); @@ -307,7 +312,7 @@ // Check that adding a bit in the final partial word does count. { idx_t index = unaligned_size - 2; - ASSERT_LE(BitMap::word_align_down(unaligned_size), index); + ASSERT_LE(word_align_down(unaligned_size), index); ASSERT_TRUE(x.at(index)); WithBitSet wbs(y, index); @@ -328,8 +333,8 @@ static void check_tail_unmodified(BitMapMemory& mem, idx_t bits, bm_word_t fill_word) { - if (!BitMap::is_word_aligned(bits)) { - idx_t last_word_bit_index = BitMap::word_align_down(bits); + if (!is_aligned(bits, BitsPerWord)) { + idx_t last_word_bit_index = word_align_down(bits); idx_t last_word_index = BitMap::calc_size_in_words(last_word_bit_index); bm_word_t last_word = mem.memory()[last_word_index]; idx_t shift = bits - last_word_bit_index;