Path: blob/master/src/hotspot/share/utilities/bitMap.hpp
40949 views
/*1* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_UTILITIES_BITMAP_HPP25#define SHARE_UTILITIES_BITMAP_HPP2627#include "memory/allocation.hpp"28#include "runtime/atomic.hpp"29#include "utilities/globalDefinitions.hpp"3031// Forward decl;32class BitMapClosure;3334// Operations for bitmaps represented as arrays of unsigned integers.35// Bits are numbered from 0 to size-1.3637// The "abstract" base BitMap class.38//39// The constructor and destructor are protected to prevent40// creation of BitMap instances outside of the BitMap class.41//42// The BitMap class doesn't use virtual calls on purpose,43// this ensures that we don't get a vtable unnecessarily.44//45// The allocation of the backing storage for the BitMap are handled by46// the subclasses. BitMap doesn't allocate or delete backing storage.47class BitMap {48friend class BitMap2D;4950public:51typedef size_t idx_t; // Type used for bit and word indices.52typedef uintptr_t bm_word_t; // Element type of array that represents the53// bitmap, with BitsPerWord bits per element.54// If this were to fail, there are lots of places that would need repair.55STATIC_ASSERT((sizeof(bm_word_t) * BitsPerByte) == BitsPerWord);5657// Hints for range sizes.58typedef enum {59unknown_range, small_range, large_range60} RangeSizeHint;6162private:63bm_word_t* _map; // First word in bitmap64idx_t _size; // Size of bitmap (in bits)6566// The maximum allowable size of a bitmap, in words or bits.67// Limit max_size_in_bits so aligning up to a word boundary never overflows.68static idx_t max_size_in_words() { return raw_to_words_align_down(~idx_t(0)); }69static idx_t max_size_in_bits() { return max_size_in_words() * BitsPerWord; }7071// Assumes relevant validity checking for bit has already been done.72static idx_t raw_to_words_align_up(idx_t bit) {73return raw_to_words_align_down(bit + (BitsPerWord - 1));74}7576// Assumes relevant validity checking for bit has already been done.77static idx_t raw_to_words_align_down(idx_t bit) {78return bit >> LogBitsPerWord;79}8081// Word-aligns bit and converts it to a word offset.82// precondition: bit <= size()83idx_t to_words_align_up(idx_t bit) const {84verify_limit(bit);85return raw_to_words_align_up(bit);86}8788// Word-aligns bit and converts it to a word offset.89// precondition: bit <= size()90inline idx_t to_words_align_down(idx_t bit) const {91verify_limit(bit);92return raw_to_words_align_down(bit);93}9495// Helper for get_next_{zero,one}_bit variants.96// - flip designates whether searching for 1s or 0s. Must be one of97// find_{zeros,ones}_flip.98// - aligned_right is true if r_index is a priori on a bm_word_t boundary.99template<bm_word_t flip, bool aligned_right>100inline idx_t get_next_bit_impl(idx_t l_index, idx_t r_index) const;101102// Values for get_next_bit_impl flip parameter.103static const bm_word_t find_ones_flip = 0;104static const bm_word_t find_zeros_flip = ~(bm_word_t)0;105106// Threshold for performing small range operation, even when large range107// operation was requested. Measured in words.108static const size_t small_range_words = 32;109110static bool is_small_range_of_words(idx_t beg_full_word, idx_t end_full_word);111112protected:113// Return the position of bit within the word that contains it (e.g., if114// bitmap words are 32 bits, return a number 0 <= n <= 31).115static idx_t bit_in_word(idx_t bit) { return bit & (BitsPerWord - 1); }116117// Return a mask that will select the specified bit, when applied to the word118// containing the bit.119static bm_word_t bit_mask(idx_t bit) { return (bm_word_t)1 << bit_in_word(bit); }120121// Return the bit number of the first bit in the specified word.122static idx_t bit_index(idx_t word) { return word << LogBitsPerWord; }123124// Return the array of bitmap words, or a specific word from it.125bm_word_t* map() { return _map; }126const bm_word_t* map() const { return _map; }127bm_word_t map(idx_t word) const { return _map[word]; }128129// Return a pointer to the word containing the specified bit.130bm_word_t* word_addr(idx_t bit) {131return map() + to_words_align_down(bit);132}133const bm_word_t* word_addr(idx_t bit) const {134return map() + to_words_align_down(bit);135}136137// Set a word to a specified value or to all ones; clear a word.138void set_word (idx_t word, bm_word_t val) { _map[word] = val; }139void set_word (idx_t word) { set_word(word, ~(bm_word_t)0); }140void clear_word(idx_t word) { _map[word] = 0; }141142static inline const bm_word_t load_word_ordered(const volatile bm_word_t* const addr, atomic_memory_order memory_order);143144// Utilities for ranges of bits. Ranges are half-open [beg, end).145146// Ranges within a single word.147bm_word_t inverted_bit_mask_for_range(idx_t beg, idx_t end) const;148void set_range_within_word (idx_t beg, idx_t end);149void clear_range_within_word (idx_t beg, idx_t end);150void par_put_range_within_word (idx_t beg, idx_t end, bool value);151152// Ranges spanning entire words.153void set_range_of_words (idx_t beg, idx_t end);154void clear_range_of_words (idx_t beg, idx_t end);155void set_large_range_of_words (idx_t beg, idx_t end);156void clear_large_range_of_words (idx_t beg, idx_t end);157158static void clear_range_of_words(bm_word_t* map, idx_t beg, idx_t end);159160idx_t count_one_bits_within_word(idx_t beg, idx_t end) const;161idx_t count_one_bits_in_range_of_words(idx_t beg_full_word, idx_t end_full_word) const;162163// Verification.164165// Verify size_in_bits does not exceed max_size_in_bits().166static void verify_size(idx_t size_in_bits) NOT_DEBUG_RETURN;167// Verify bit is less than size().168void verify_index(idx_t bit) const NOT_DEBUG_RETURN;169// Verify bit is not greater than size().170void verify_limit(idx_t bit) const NOT_DEBUG_RETURN;171// Verify [beg,end) is a valid range, e.g. beg <= end <= size().172void verify_range(idx_t beg, idx_t end) const NOT_DEBUG_RETURN;173174// Allocation Helpers.175176// Allocates and clears the bitmap memory.177template <class Allocator>178static bm_word_t* allocate(const Allocator&, idx_t size_in_bits, bool clear = true);179180// Reallocates and clears the new bitmap memory.181template <class Allocator>182static bm_word_t* reallocate(const Allocator&, bm_word_t* map, idx_t old_size_in_bits, idx_t new_size_in_bits, bool clear = true);183184// Free the bitmap memory.185template <class Allocator>186static void free(const Allocator&, bm_word_t* map, idx_t size_in_bits);187188// Protected functions, that are used by BitMap sub-classes that support them.189190// Resize the backing bitmap memory.191//192// Old bits are transfered to the new memory193// and the extended memory is cleared.194template <class Allocator>195void resize(const Allocator& allocator, idx_t new_size_in_bits, bool clear);196197// Set up and clear the bitmap memory.198//199// Precondition: The bitmap was default constructed and has200// not yet had memory allocated via resize or (re)initialize.201template <class Allocator>202void initialize(const Allocator& allocator, idx_t size_in_bits, bool clear);203204// Set up and clear the bitmap memory.205//206// Can be called on previously initialized bitmaps.207template <class Allocator>208void reinitialize(const Allocator& allocator, idx_t new_size_in_bits, bool clear);209210// Set the map and size.211void update(bm_word_t* map, idx_t size) {212_map = map;213_size = size;214}215216// Protected constructor and destructor.217BitMap(bm_word_t* map, idx_t size_in_bits) : _map(map), _size(size_in_bits) {218verify_size(size_in_bits);219}220~BitMap() {}221222public:223// Pretouch the entire range of memory this BitMap covers.224void pretouch();225226// Accessing227static idx_t calc_size_in_words(size_t size_in_bits) {228verify_size(size_in_bits);229return raw_to_words_align_up(size_in_bits);230}231232idx_t size() const { return _size; }233idx_t size_in_words() const { return calc_size_in_words(size()); }234idx_t size_in_bytes() const { return size_in_words() * BytesPerWord; }235236bool at(idx_t index) const {237verify_index(index);238return (*word_addr(index) & bit_mask(index)) != 0;239}240241// memory_order must be memory_order_relaxed or memory_order_acquire.242bool par_at(idx_t index, atomic_memory_order memory_order = memory_order_acquire) const;243244// Set or clear the specified bit.245inline void set_bit(idx_t bit);246inline void clear_bit(idx_t bit);247248// Attempts to change a bit to a desired value. The operation returns true if249// this thread changed the value of the bit. It was changed with a RMW operation250// using the specified memory_order. The operation returns false if the change251// could not be set due to the bit already being observed in the desired state.252// The atomic access that observed the bit in the desired state has acquire253// semantics, unless memory_order is memory_order_relaxed or memory_order_release.254inline bool par_set_bit(idx_t bit, atomic_memory_order memory_order = memory_order_conservative);255inline bool par_clear_bit(idx_t bit, atomic_memory_order memory_order = memory_order_conservative);256257// Put the given value at the given index. The parallel version258// will CAS the value into the bitmap and is quite a bit slower.259// The parallel version also returns a value indicating if the260// calling thread was the one that changed the value of the bit.261void at_put(idx_t index, bool value);262bool par_at_put(idx_t index, bool value);263264// Update a range of bits. Ranges are half-open [beg, end).265void set_range (idx_t beg, idx_t end);266void clear_range (idx_t beg, idx_t end);267void set_large_range (idx_t beg, idx_t end);268void clear_large_range (idx_t beg, idx_t end);269void at_put_range(idx_t beg, idx_t end, bool value);270void par_at_put_range(idx_t beg, idx_t end, bool value);271void at_put_large_range(idx_t beg, idx_t end, bool value);272void par_at_put_large_range(idx_t beg, idx_t end, bool value);273274// Update a range of bits, using a hint about the size. Currently only275// inlines the predominant case of a 1-bit range. Works best when hint is a276// compile-time constant.277void set_range(idx_t beg, idx_t end, RangeSizeHint hint);278void clear_range(idx_t beg, idx_t end, RangeSizeHint hint);279void par_set_range(idx_t beg, idx_t end, RangeSizeHint hint);280void par_clear_range (idx_t beg, idx_t end, RangeSizeHint hint);281282// Clearing283void clear_large();284inline void clear();285286// Iteration support. Applies the closure to the index for each set bit,287// starting from the least index in the range to the greatest, in order.288// The iteration terminates if the closure returns false. Returns true if289// the iteration completed, false if terminated early because the closure290// returned false. If the closure modifies the bitmap, modifications to291// bits at indices greater than the current index will affect which further292// indices the closure will be applied to.293// precondition: beg and end form a valid range.294bool iterate(BitMapClosure* cl, idx_t beg, idx_t end);295bool iterate(BitMapClosure* cl);296297// Looking for 1's and 0's at indices equal to or greater than "l_index",298// stopping if none has been found before "r_index", and returning299// "r_index" (which must be at most "size") in that case.300idx_t get_next_one_offset (idx_t l_index, idx_t r_index) const;301idx_t get_next_zero_offset(idx_t l_index, idx_t r_index) const;302303idx_t get_next_one_offset(idx_t offset) const {304return get_next_one_offset(offset, size());305}306idx_t get_next_zero_offset(idx_t offset) const {307return get_next_zero_offset(offset, size());308}309310// Like "get_next_one_offset", except requires that "r_index" is311// aligned to bitsizeof(bm_word_t).312idx_t get_next_one_offset_aligned_right(idx_t l_index, idx_t r_index) const;313314// Returns the number of bits set in the bitmap.315idx_t count_one_bits() const;316317// Returns the number of bits set within [beg, end).318idx_t count_one_bits(idx_t beg, idx_t end) const;319320// Set operations.321void set_union(const BitMap& bits);322void set_difference(const BitMap& bits);323void set_intersection(const BitMap& bits);324// Returns true iff "this" is a superset of "bits".325bool contains(const BitMap& bits) const;326// Returns true iff "this and "bits" have a non-empty intersection.327bool intersects(const BitMap& bits) const;328329// Returns result of whether this map changed330// during the operation331bool set_union_with_result(const BitMap& bits);332bool set_difference_with_result(const BitMap& bits);333bool set_intersection_with_result(const BitMap& bits);334335void set_from(const BitMap& bits);336337bool is_same(const BitMap& bits) const;338339// Test if all bits are set or cleared340bool is_full() const;341bool is_empty() const;342343void write_to(bm_word_t* buffer, size_t buffer_size_in_bytes) const;344void print_on_error(outputStream* st, const char* prefix) const;345346#ifndef PRODUCT347public:348// Printing349void print_on(outputStream* st) const;350#endif351};352353// A concrete implementation of the the "abstract" BitMap class.354//355// The BitMapView is used when the backing storage is managed externally.356class BitMapView : public BitMap {357public:358BitMapView() : BitMap(NULL, 0) {}359BitMapView(bm_word_t* map, idx_t size_in_bits) : BitMap(map, size_in_bits) {}360};361362// A BitMap with storage in a ResourceArea.363class ResourceBitMap : public BitMap {364365public:366ResourceBitMap() : BitMap(NULL, 0) {}367// Conditionally clears the bitmap memory.368ResourceBitMap(idx_t size_in_bits, bool clear = true);369370// Resize the backing bitmap memory.371//372// Old bits are transfered to the new memory373// and the extended memory is cleared.374void resize(idx_t new_size_in_bits);375376// Set up and clear the bitmap memory.377//378// Precondition: The bitmap was default constructed and has379// not yet had memory allocated via resize or initialize.380void initialize(idx_t size_in_bits);381382// Set up and clear the bitmap memory.383//384// Can be called on previously initialized bitmaps.385void reinitialize(idx_t size_in_bits);386};387388// A BitMap with storage in a specific Arena.389class ArenaBitMap : public BitMap {390public:391// Clears the bitmap memory.392ArenaBitMap(Arena* arena, idx_t size_in_bits);393394private:395NONCOPYABLE(ArenaBitMap);396};397398// A BitMap with storage in the CHeap.399class CHeapBitMap : public BitMap {400401private:402// Don't allow copy or assignment, to prevent the403// allocated memory from leaking out to other instances.404NONCOPYABLE(CHeapBitMap);405406// NMT memory type407MEMFLAGS _flags;408409public:410CHeapBitMap(MEMFLAGS flags = mtInternal) : BitMap(NULL, 0), _flags(flags) {}411// Clears the bitmap memory.412CHeapBitMap(idx_t size_in_bits, MEMFLAGS flags = mtInternal, bool clear = true);413~CHeapBitMap();414415// Resize the backing bitmap memory.416//417// Old bits are transfered to the new memory418// and the extended memory is (optionally) cleared.419void resize(idx_t new_size_in_bits, bool clear = true);420421// Set up and (optionally) clear the bitmap memory.422//423// Precondition: The bitmap was default constructed and has424// not yet had memory allocated via resize or initialize.425void initialize(idx_t size_in_bits, bool clear = true);426427// Set up and (optionally) clear the bitmap memory.428//429// Can be called on previously initialized bitmaps.430void reinitialize(idx_t size_in_bits, bool clear = true);431};432433// Convenience class wrapping BitMap which provides multiple bits per slot.434class BitMap2D {435public:436typedef BitMap::idx_t idx_t; // Type used for bit and word indices.437typedef BitMap::bm_word_t bm_word_t; // Element type of array that438// represents the bitmap.439private:440ResourceBitMap _map;441idx_t _bits_per_slot;442443idx_t bit_index(idx_t slot_index, idx_t bit_within_slot_index) const {444return slot_index * _bits_per_slot + bit_within_slot_index;445}446447void verify_bit_within_slot_index(idx_t index) const {448assert(index < _bits_per_slot, "bit_within_slot index out of bounds");449}450451public:452// Construction. bits_per_slot must be greater than 0.453BitMap2D(idx_t bits_per_slot) :454_map(), _bits_per_slot(bits_per_slot) {}455456// Allocates necessary data structure in resource area. bits_per_slot must be greater than 0.457BitMap2D(idx_t size_in_slots, idx_t bits_per_slot) :458_map(size_in_slots * bits_per_slot), _bits_per_slot(bits_per_slot) {}459460idx_t size_in_bits() {461return _map.size();462}463464bool is_valid_index(idx_t slot_index, idx_t bit_within_slot_index);465bool at(idx_t slot_index, idx_t bit_within_slot_index) const;466void set_bit(idx_t slot_index, idx_t bit_within_slot_index);467void clear_bit(idx_t slot_index, idx_t bit_within_slot_index);468void at_put(idx_t slot_index, idx_t bit_within_slot_index, bool value);469void at_put_grow(idx_t slot_index, idx_t bit_within_slot_index, bool value);470};471472// Closure for iterating over BitMaps473474class BitMapClosure {475public:476// Callback when bit in map is set. Should normally return "true";477// return of false indicates that the bitmap iteration should terminate.478virtual bool do_bit(BitMap::idx_t index) = 0;479};480481#endif // SHARE_UTILITIES_BITMAP_HPP482483484