src/share/vm/utilities/bitMap.hpp

Thu, 20 Nov 2008 16:56:09 -0800

author
ysr
date
Thu, 20 Nov 2008 16:56:09 -0800
changeset 888
c96030fff130
parent 777
37f87013dfd8
child 1244
6e2afda171db
permissions
-rw-r--r--

6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa

duke@435 1 /*
duke@435 2 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
duke@435 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
duke@435 20 * CA 95054 USA or visit www.sun.com if you need additional information or
duke@435 21 * have any questions.
duke@435 22 *
duke@435 23 */
duke@435 24
ysr@777 25 // Forward decl;
ysr@777 26 class BitMapClosure;
duke@435 27
ysr@777 28 // Operations for bitmaps represented as arrays of unsigned integers.
ysr@777 29 // Bit offsets are numbered from 0 to size-1.
duke@435 30
duke@435 31 class BitMap VALUE_OBJ_CLASS_SPEC {
duke@435 32 friend class BitMap2D;
duke@435 33
duke@435 34 public:
duke@435 35 typedef size_t idx_t; // Type used for bit and word indices.
ysr@777 36 typedef uintptr_t bm_word_t; // Element type of array that represents
ysr@777 37 // the bitmap.
duke@435 38
duke@435 39 // Hints for range sizes.
duke@435 40 typedef enum {
duke@435 41 unknown_range, small_range, large_range
duke@435 42 } RangeSizeHint;
duke@435 43
duke@435 44 private:
ysr@777 45 bm_word_t* _map; // First word in bitmap
ysr@777 46 idx_t _size; // Size of bitmap (in bits)
duke@435 47
duke@435 48 // Puts the given value at the given offset, using resize() to size
duke@435 49 // the bitmap appropriately if needed using factor-of-two expansion.
duke@435 50 void at_put_grow(idx_t index, bool value);
duke@435 51
duke@435 52 protected:
duke@435 53 // Return the position of bit within the word that contains it (e.g., if
duke@435 54 // bitmap words are 32 bits, return a number 0 <= n <= 31).
duke@435 55 static idx_t bit_in_word(idx_t bit) { return bit & (BitsPerWord - 1); }
duke@435 56
duke@435 57 // Return a mask that will select the specified bit, when applied to the word
duke@435 58 // containing the bit.
ysr@777 59 static bm_word_t bit_mask(idx_t bit) { return (bm_word_t)1 << bit_in_word(bit); }
duke@435 60
duke@435 61 // Return the index of the word containing the specified bit.
duke@435 62 static idx_t word_index(idx_t bit) { return bit >> LogBitsPerWord; }
duke@435 63
duke@435 64 // Return the bit number of the first bit in the specified word.
duke@435 65 static idx_t bit_index(idx_t word) { return word << LogBitsPerWord; }
duke@435 66
duke@435 67 // Return the array of bitmap words, or a specific word from it.
ysr@777 68 bm_word_t* map() const { return _map; }
ysr@777 69 bm_word_t map(idx_t word) const { return _map[word]; }
duke@435 70
duke@435 71 // Return a pointer to the word containing the specified bit.
ysr@777 72 bm_word_t* word_addr(idx_t bit) const { return map() + word_index(bit); }
duke@435 73
duke@435 74 // Set a word to a specified value or to all ones; clear a word.
ysr@777 75 void set_word (idx_t word, bm_word_t val) { _map[word] = val; }
duke@435 76 void set_word (idx_t word) { set_word(word, ~(uintptr_t)0); }
duke@435 77 void clear_word(idx_t word) { _map[word] = 0; }
duke@435 78
duke@435 79 // Utilities for ranges of bits. Ranges are half-open [beg, end).
duke@435 80
duke@435 81 // Ranges within a single word.
ysr@777 82 bm_word_t inverted_bit_mask_for_range(idx_t beg, idx_t end) const;
ysr@777 83 void set_range_within_word (idx_t beg, idx_t end);
ysr@777 84 void clear_range_within_word (idx_t beg, idx_t end);
ysr@777 85 void par_put_range_within_word (idx_t beg, idx_t end, bool value);
duke@435 86
duke@435 87 // Ranges spanning entire words.
ysr@777 88 void set_range_of_words (idx_t beg, idx_t end);
ysr@777 89 void clear_range_of_words (idx_t beg, idx_t end);
ysr@777 90 void set_large_range_of_words (idx_t beg, idx_t end);
ysr@777 91 void clear_large_range_of_words (idx_t beg, idx_t end);
duke@435 92
duke@435 93 // The index of the first full word in a range.
ysr@777 94 idx_t word_index_round_up(idx_t bit) const;
duke@435 95
duke@435 96 // Verification, statistics.
ysr@777 97 void verify_index(idx_t index) const;
ysr@777 98 void verify_range(idx_t beg_index, idx_t end_index) const;
duke@435 99
ysr@777 100 static idx_t* _pop_count_table;
ysr@777 101 static void init_pop_count_table();
ysr@777 102 static idx_t num_set_bits(bm_word_t w);
ysr@777 103 static idx_t num_set_bits_from_table(unsigned char c);
duke@435 104
duke@435 105 public:
duke@435 106
duke@435 107 // Constructs a bitmap with no map, and size 0.
duke@435 108 BitMap() : _map(NULL), _size(0) {}
duke@435 109
ysr@777 110 // Constructs a bitmap with the given map and size.
ysr@777 111 BitMap(bm_word_t* map, idx_t size_in_bits);
duke@435 112
ysr@777 113 // Constructs an empty bitmap of the given size (that is, this clears the
ysr@777 114 // new bitmap). Allocates the map array in resource area if
ysr@777 115 // "in_resource_area" is true, else in the C heap.
ysr@777 116 BitMap(idx_t size_in_bits, bool in_resource_area = true);
duke@435 117
ysr@777 118 // Set the map and size.
ysr@777 119 void set_map(bm_word_t* map) { _map = map; }
duke@435 120 void set_size(idx_t size_in_bits) { _size = size_in_bits; }
duke@435 121
ysr@777 122 // Allocates necessary data structure, either in the resource area
ysr@777 123 // or in the C heap, as indicated by "in_resource_area."
duke@435 124 // Preserves state currently in bit map by copying data.
duke@435 125 // Zeros any newly-addressable bits.
ysr@777 126 // If "in_resource_area" is false, frees the current map.
ysr@777 127 // (Note that this assumes that all calls to "resize" on the same BitMap
ysr@777 128 // use the same value for "in_resource_area".)
ysr@777 129 void resize(idx_t size_in_bits, bool in_resource_area = true);
duke@435 130
duke@435 131 // Accessing
duke@435 132 idx_t size() const { return _size; }
duke@435 133 idx_t size_in_words() const {
duke@435 134 return word_index(size() + BitsPerWord - 1);
duke@435 135 }
duke@435 136
duke@435 137 bool at(idx_t index) const {
duke@435 138 verify_index(index);
duke@435 139 return (*word_addr(index) & bit_mask(index)) != 0;
duke@435 140 }
duke@435 141
duke@435 142 // Align bit index up or down to the next bitmap word boundary, or check
duke@435 143 // alignment.
duke@435 144 static idx_t word_align_up(idx_t bit) {
duke@435 145 return align_size_up(bit, BitsPerWord);
duke@435 146 }
duke@435 147 static idx_t word_align_down(idx_t bit) {
duke@435 148 return align_size_down(bit, BitsPerWord);
duke@435 149 }
duke@435 150 static bool is_word_aligned(idx_t bit) {
duke@435 151 return word_align_up(bit) == bit;
duke@435 152 }
duke@435 153
duke@435 154 // Set or clear the specified bit.
duke@435 155 inline void set_bit(idx_t bit);
ysr@777 156 void clear_bit(idx_t bit);
duke@435 157
duke@435 158 // Atomically set or clear the specified bit.
ysr@777 159 bool par_set_bit(idx_t bit);
ysr@777 160 bool par_clear_bit(idx_t bit);
duke@435 161
duke@435 162 // Put the given value at the given offset. The parallel version
duke@435 163 // will CAS the value into the bitmap and is quite a bit slower.
duke@435 164 // The parallel version also returns a value indicating if the
duke@435 165 // calling thread was the one that changed the value of the bit.
duke@435 166 void at_put(idx_t index, bool value);
duke@435 167 bool par_at_put(idx_t index, bool value);
duke@435 168
duke@435 169 // Update a range of bits. Ranges are half-open [beg, end).
duke@435 170 void set_range (idx_t beg, idx_t end);
duke@435 171 void clear_range (idx_t beg, idx_t end);
duke@435 172 void set_large_range (idx_t beg, idx_t end);
duke@435 173 void clear_large_range (idx_t beg, idx_t end);
duke@435 174 void at_put_range(idx_t beg, idx_t end, bool value);
duke@435 175 void par_at_put_range(idx_t beg, idx_t end, bool value);
duke@435 176 void at_put_large_range(idx_t beg, idx_t end, bool value);
duke@435 177 void par_at_put_large_range(idx_t beg, idx_t end, bool value);
duke@435 178
duke@435 179 // Update a range of bits, using a hint about the size. Currently only
duke@435 180 // inlines the predominant case of a 1-bit range. Works best when hint is a
duke@435 181 // compile-time constant.
ysr@777 182 void set_range(idx_t beg, idx_t end, RangeSizeHint hint);
ysr@777 183 void clear_range(idx_t beg, idx_t end, RangeSizeHint hint);
ysr@777 184 void par_set_range(idx_t beg, idx_t end, RangeSizeHint hint);
ysr@777 185 void par_clear_range (idx_t beg, idx_t end, RangeSizeHint hint);
ysr@777 186
ysr@777 187 // It performs the union operation between subsets of equal length
ysr@777 188 // of two bitmaps (the target bitmap of the method and the
ysr@777 189 // from_bitmap) and stores the result to the target bitmap. The
ysr@777 190 // from_start_index represents the first bit index of the subrange
ysr@777 191 // of the from_bitmap. The to_start_index is the equivalent of the
ysr@777 192 // target bitmap. Both indexes should be word-aligned, i.e. they
ysr@777 193 // should correspond to the first bit on a bitmap word (it's up to
ysr@777 194 // the caller to ensure this; the method does check it). The length
ysr@777 195 // of the subset is specified with word_num and it is in number of
ysr@777 196 // bitmap words. The caller should ensure that this is at least 2
ysr@777 197 // (smaller ranges are not support to save extra checks). Again,
ysr@777 198 // this is checked in the method.
ysr@777 199 //
ysr@777 200 // Atomicity concerns: it is assumed that any contention on the
ysr@777 201 // target bitmap with other threads will happen on the first and
ysr@777 202 // last words; the ones in between will be "owned" exclusively by
ysr@777 203 // the calling thread and, in fact, they will already be 0. So, the
ysr@777 204 // method performs a CAS on the first word, copies the next
ysr@777 205 // word_num-2 words, and finally performs a CAS on the last word.
ysr@777 206 void mostly_disjoint_range_union(BitMap* from_bitmap,
ysr@777 207 idx_t from_start_index,
ysr@777 208 idx_t to_start_index,
ysr@777 209 size_t word_num);
ysr@777 210
duke@435 211
duke@435 212 // Clearing
duke@435 213 void clear_large();
ysr@777 214 inline void clear();
duke@435 215
ysr@777 216 // Iteration support. Returns "true" if the iteration completed, false
ysr@777 217 // if the iteration terminated early (because the closure "blk" returned
ysr@777 218 // false).
ysr@777 219 bool iterate(BitMapClosure* blk, idx_t leftIndex, idx_t rightIndex);
ysr@777 220 bool iterate(BitMapClosure* blk) {
duke@435 221 // call the version that takes an interval
ysr@777 222 return iterate(blk, 0, size());
duke@435 223 }
duke@435 224
ysr@777 225 // Looking for 1's and 0's at indices equal to or greater than "l_index",
ysr@777 226 // stopping if none has been found before "r_index", and returning
ysr@777 227 // "r_index" (which must be at most "size") in that case.
ysr@777 228 idx_t get_next_one_offset_inline (idx_t l_index, idx_t r_index) const;
ysr@777 229 idx_t get_next_zero_offset_inline(idx_t l_index, idx_t r_index) const;
ysr@777 230
ysr@777 231 // Like "get_next_one_offset_inline", except requires that "r_index" is
ysr@777 232 // aligned to bitsizeof(bm_word_t).
ysr@777 233 idx_t get_next_one_offset_inline_aligned_right(idx_t l_index,
ysr@777 234 idx_t r_index) const;
ysr@777 235
ysr@777 236 // Non-inline versionsof the above.
duke@435 237 idx_t get_next_one_offset (idx_t l_index, idx_t r_index) const;
duke@435 238 idx_t get_next_zero_offset(idx_t l_index, idx_t r_index) const;
duke@435 239
duke@435 240 idx_t get_next_one_offset(idx_t offset) const {
duke@435 241 return get_next_one_offset(offset, size());
duke@435 242 }
duke@435 243 idx_t get_next_zero_offset(idx_t offset) const {
duke@435 244 return get_next_zero_offset(offset, size());
duke@435 245 }
duke@435 246
ysr@777 247 // Returns the number of bits set in the bitmap.
ysr@777 248 idx_t count_one_bits() const;
duke@435 249
duke@435 250 // Set operations.
duke@435 251 void set_union(BitMap bits);
duke@435 252 void set_difference(BitMap bits);
duke@435 253 void set_intersection(BitMap bits);
duke@435 254 // Returns true iff "this" is a superset of "bits".
duke@435 255 bool contains(const BitMap bits) const;
duke@435 256 // Returns true iff "this and "bits" have a non-empty intersection.
duke@435 257 bool intersects(const BitMap bits) const;
duke@435 258
duke@435 259 // Returns result of whether this map changed
duke@435 260 // during the operation
duke@435 261 bool set_union_with_result(BitMap bits);
duke@435 262 bool set_difference_with_result(BitMap bits);
duke@435 263 bool set_intersection_with_result(BitMap bits);
duke@435 264
ysr@777 265 // Requires the submap of "bits" starting at offset to be at least as
ysr@777 266 // large as "this". Modifies "this" to be the intersection of its
ysr@777 267 // current contents and the submap of "bits" starting at "offset" of the
ysr@777 268 // same length as "this."
ysr@777 269 // (For expedience, currently requires the offset to be aligned to the
ysr@777 270 // bitsize of a uintptr_t. This should go away in the future though it
ysr@777 271 // will probably remain a good case to optimize.)
ysr@777 272 void set_intersection_at_offset(BitMap bits, idx_t offset);
ysr@777 273
duke@435 274 void set_from(BitMap bits);
duke@435 275
duke@435 276 bool is_same(BitMap bits);
duke@435 277
duke@435 278 // Test if all bits are set or cleared
duke@435 279 bool is_full() const;
duke@435 280 bool is_empty() const;
duke@435 281
duke@435 282
duke@435 283 #ifndef PRODUCT
duke@435 284 public:
duke@435 285 // Printing
duke@435 286 void print_on(outputStream* st) const;
duke@435 287 #endif
duke@435 288 };
duke@435 289
duke@435 290
duke@435 291 // Convenience class wrapping BitMap which provides multiple bits per slot.
duke@435 292 class BitMap2D VALUE_OBJ_CLASS_SPEC {
duke@435 293 public:
ysr@777 294 typedef BitMap::idx_t idx_t; // Type used for bit and word indices.
ysr@777 295 typedef BitMap::bm_word_t bm_word_t; // Element type of array that
ysr@777 296 // represents the bitmap.
duke@435 297 private:
duke@435 298 BitMap _map;
duke@435 299 idx_t _bits_per_slot;
duke@435 300
duke@435 301 idx_t bit_index(idx_t slot_index, idx_t bit_within_slot_index) const {
duke@435 302 return slot_index * _bits_per_slot + bit_within_slot_index;
duke@435 303 }
duke@435 304
duke@435 305 void verify_bit_within_slot_index(idx_t index) const {
duke@435 306 assert(index < _bits_per_slot, "bit_within_slot index out of bounds");
duke@435 307 }
duke@435 308
duke@435 309 public:
duke@435 310 // Construction. bits_per_slot must be greater than 0.
ysr@777 311 BitMap2D(bm_word_t* map, idx_t size_in_slots, idx_t bits_per_slot);
duke@435 312
duke@435 313 // Allocates necessary data structure in resource area. bits_per_slot must be greater than 0.
duke@435 314 BitMap2D(idx_t size_in_slots, idx_t bits_per_slot);
duke@435 315
duke@435 316 idx_t size_in_bits() {
duke@435 317 return _map.size();
duke@435 318 }
duke@435 319
duke@435 320 // Returns number of full slots that have been allocated
duke@435 321 idx_t size_in_slots() {
duke@435 322 // Round down
duke@435 323 return _map.size() / _bits_per_slot;
duke@435 324 }
duke@435 325
duke@435 326 bool is_valid_index(idx_t slot_index, idx_t bit_within_slot_index) {
duke@435 327 verify_bit_within_slot_index(bit_within_slot_index);
duke@435 328 return (bit_index(slot_index, bit_within_slot_index) < size_in_bits());
duke@435 329 }
duke@435 330
duke@435 331 bool at(idx_t slot_index, idx_t bit_within_slot_index) const {
duke@435 332 verify_bit_within_slot_index(bit_within_slot_index);
duke@435 333 return _map.at(bit_index(slot_index, bit_within_slot_index));
duke@435 334 }
duke@435 335
duke@435 336 void set_bit(idx_t slot_index, idx_t bit_within_slot_index) {
duke@435 337 verify_bit_within_slot_index(bit_within_slot_index);
duke@435 338 _map.set_bit(bit_index(slot_index, bit_within_slot_index));
duke@435 339 }
duke@435 340
duke@435 341 void clear_bit(idx_t slot_index, idx_t bit_within_slot_index) {
duke@435 342 verify_bit_within_slot_index(bit_within_slot_index);
duke@435 343 _map.clear_bit(bit_index(slot_index, bit_within_slot_index));
duke@435 344 }
duke@435 345
duke@435 346 void at_put(idx_t slot_index, idx_t bit_within_slot_index, bool value) {
duke@435 347 verify_bit_within_slot_index(bit_within_slot_index);
duke@435 348 _map.at_put(bit_index(slot_index, bit_within_slot_index), value);
duke@435 349 }
duke@435 350
duke@435 351 void at_put_grow(idx_t slot_index, idx_t bit_within_slot_index, bool value) {
duke@435 352 verify_bit_within_slot_index(bit_within_slot_index);
duke@435 353 _map.at_put_grow(bit_index(slot_index, bit_within_slot_index), value);
duke@435 354 }
duke@435 355
ysr@777 356 void clear();
duke@435 357 };
duke@435 358
ysr@777 359 // Closure for iterating over BitMaps
duke@435 360
ysr@777 361 class BitMapClosure VALUE_OBJ_CLASS_SPEC {
ysr@777 362 public:
ysr@777 363 // Callback when bit in map is set. Should normally return "true";
ysr@777 364 // return of false indicates that the bitmap iteration should terminate.
ysr@777 365 virtual bool do_bit(BitMap::idx_t offset) = 0;
ysr@777 366 };

mercurial