bitMap.hpp 13.0 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24
 *
 */

25 26 27 28 29 30
#ifndef SHARE_VM_UTILITIES_BITMAP_HPP
#define SHARE_VM_UTILITIES_BITMAP_HPP

#include "memory/allocation.hpp"
#include "utilities/top.hpp"

31 32
// Forward decl;
class BitMapClosure;
D
duke 已提交
33

34 35
// Operations for bitmaps represented as arrays of unsigned integers.
// Bit offsets are numbered from 0 to size-1.
D
duke 已提交
36 37 38 39 40 41

class BitMap VALUE_OBJ_CLASS_SPEC {
  friend class BitMap2D;

 public:
  typedef size_t idx_t;         // Type used for bit and word indices.
42 43
  typedef uintptr_t bm_word_t;  // Element type of array that represents
                                // the bitmap.
D
duke 已提交
44 45 46 47 48 49 50

  // Hints for range sizes.
  typedef enum {
    unknown_range, small_range, large_range
  } RangeSizeHint;

 private:
51
  ArrayAllocator<bm_word_t, mtInternal> _map_allocator;
52 53
  bm_word_t* _map;     // First word in bitmap
  idx_t      _size;    // Size of bitmap (in bits)
D
duke 已提交
54 55 56 57 58 59 60 61 62 63 64 65

  // Puts the given value at the given offset, using resize() to size
  // the bitmap appropriately if needed using factor-of-two expansion.
  void at_put_grow(idx_t index, bool value);

 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).
  static idx_t bit_in_word(idx_t bit) { return bit & (BitsPerWord - 1); }

  // Return a mask that will select the specified bit, when applied to the word
  // containing the bit.
66
  static bm_word_t bit_mask(idx_t bit) { return (bm_word_t)1 << bit_in_word(bit); }
D
duke 已提交
67 68 69 70 71 72 73 74

  // 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; }

  // Return the array of bitmap words, or a specific word from it.
75 76
  bm_word_t* map() const           { return _map; }
  bm_word_t  map(idx_t word) const { return _map[word]; }
D
duke 已提交
77 78

  // Return a pointer to the word containing the specified bit.
79
  bm_word_t* word_addr(idx_t bit) const { return map() + word_index(bit); }
D
duke 已提交
80 81

  // Set a word to a specified value or to all ones; clear a word.
82
  void set_word  (idx_t word, bm_word_t val) { _map[word] = val; }
D
duke 已提交
83 84 85 86 87 88
  void set_word  (idx_t word)            { set_word(word, ~(uintptr_t)0); }
  void clear_word(idx_t word)            { _map[word] = 0; }

  // Utilities for ranges of bits.  Ranges are half-open [beg, end).

  // Ranges within a single word.
89 90 91 92
  bm_word_t inverted_bit_mask_for_range(idx_t beg, idx_t end) const;
  void  set_range_within_word      (idx_t beg, idx_t end);
  void  clear_range_within_word    (idx_t beg, idx_t end);
  void  par_put_range_within_word  (idx_t beg, idx_t end, bool value);
D
duke 已提交
93 94

  // Ranges spanning entire words.
95 96 97 98
  void      set_range_of_words         (idx_t beg, idx_t end);
  void      clear_range_of_words       (idx_t beg, idx_t end);
  void      set_large_range_of_words   (idx_t beg, idx_t end);
  void      clear_large_range_of_words (idx_t beg, idx_t end);
D
duke 已提交
99 100

  // The index of the first full word in a range.
101
  idx_t word_index_round_up(idx_t bit) const;
D
duke 已提交
102

103 104 105 106
  // Verification.
  inline void verify_index(idx_t index) const NOT_DEBUG_RETURN;
  inline void verify_range(idx_t beg_index, idx_t end_index) const
    NOT_DEBUG_RETURN;
D
duke 已提交
107

108
  // Statistics.
109 110 111 112
  static idx_t* _pop_count_table;
  static void init_pop_count_table();
  static idx_t num_set_bits(bm_word_t w);
  static idx_t num_set_bits_from_table(unsigned char c);
D
duke 已提交
113 114 115 116

 public:

  // Constructs a bitmap with no map, and size 0.
117
  BitMap() : _map(NULL), _size(0), _map_allocator(false) {}
D
duke 已提交
118

119 120
  // Constructs a bitmap with the given map and size.
  BitMap(bm_word_t* map, idx_t size_in_bits);
D
duke 已提交
121

122 123 124 125
  // Constructs an empty bitmap of the given size (that is, this clears the
  // new bitmap).  Allocates the map array in resource area if
  // "in_resource_area" is true, else in the C heap.
  BitMap(idx_t size_in_bits, bool in_resource_area = true);
D
duke 已提交
126

127 128
  // Set the map and size.
  void set_map(bm_word_t* map)      { _map = map; }
D
duke 已提交
129 130
  void set_size(idx_t size_in_bits) { _size = size_in_bits; }

131 132
  // Allocates necessary data structure, either in the resource area
  // or in the C heap, as indicated by "in_resource_area."
D
duke 已提交
133 134
  // Preserves state currently in bit map by copying data.
  // Zeros any newly-addressable bits.
135 136 137 138
  // If "in_resource_area" is false, frees the current map.
  // (Note that this assumes that all calls to "resize" on the same BitMap
  // use the same value for "in_resource_area".)
  void resize(idx_t size_in_bits, bool in_resource_area = true);
D
duke 已提交
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164

  // Accessing
  idx_t size() const                    { return _size; }
  idx_t size_in_words() const           {
    return word_index(size() + BitsPerWord - 1);
  }

  bool at(idx_t index) const {
    verify_index(index);
    return (*word_addr(index) & bit_mask(index)) != 0;
  }

  // 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_size_up(bit, BitsPerWord);
  }
  static idx_t word_align_down(idx_t bit) {
    return align_size_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);
165
  inline void clear_bit(idx_t bit);
D
duke 已提交
166 167

  // Atomically set or clear the specified bit.
168 169
  inline bool par_set_bit(idx_t bit);
  inline bool par_clear_bit(idx_t bit);
D
duke 已提交
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190

  // Put the given value at the given offset. 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.
  void at_put(idx_t index, bool value);
  bool par_at_put(idx_t index, bool value);

  // Update a range of bits.  Ranges are half-open [beg, end).
  void set_range   (idx_t beg, idx_t end);
  void clear_range (idx_t beg, idx_t end);
  void set_large_range   (idx_t beg, idx_t end);
  void clear_large_range (idx_t beg, idx_t end);
  void at_put_range(idx_t beg, idx_t end, bool value);
  void par_at_put_range(idx_t beg, idx_t end, bool value);
  void at_put_large_range(idx_t beg, idx_t end, bool value);
  void par_at_put_large_range(idx_t beg, idx_t end, bool value);

  // Update a range of bits, using a hint about the size.  Currently only
  // inlines the predominant case of a 1-bit range.  Works best when hint is a
  // compile-time constant.
191 192 193 194 195
  void set_range(idx_t beg, idx_t end, RangeSizeHint hint);
  void clear_range(idx_t beg, idx_t end, RangeSizeHint hint);
  void par_set_range(idx_t beg, idx_t end, RangeSizeHint hint);
  void par_clear_range  (idx_t beg, idx_t end, RangeSizeHint hint);

D
duke 已提交
196 197
  // Clearing
  void clear_large();
198
  inline void clear();
D
duke 已提交
199

200 201 202 203 204
  // Iteration support.  Returns "true" if the iteration completed, false
  // if the iteration terminated early (because the closure "blk" returned
  // false).
  bool iterate(BitMapClosure* blk, idx_t leftIndex, idx_t rightIndex);
  bool iterate(BitMapClosure* blk) {
D
duke 已提交
205
    // call the version that takes an interval
206
    return iterate(blk, 0, size());
D
duke 已提交
207 208
  }

209 210 211 212 213 214 215 216 217 218 219 220
  // Looking for 1's and 0's at indices equal to or greater than "l_index",
  // stopping if none has been found before "r_index", and returning
  // "r_index" (which must be at most "size") in that case.
  idx_t get_next_one_offset_inline (idx_t l_index, idx_t r_index) const;
  idx_t get_next_zero_offset_inline(idx_t l_index, idx_t r_index) const;

  // Like "get_next_one_offset_inline", except requires that "r_index" is
  // aligned to bitsizeof(bm_word_t).
  idx_t get_next_one_offset_inline_aligned_right(idx_t l_index,
                                                        idx_t r_index) const;

  // Non-inline versionsof the above.
D
duke 已提交
221 222 223 224 225 226 227 228 229 230
  idx_t get_next_one_offset (idx_t l_index, idx_t r_index) const;
  idx_t get_next_zero_offset(idx_t l_index, idx_t r_index) const;

  idx_t get_next_one_offset(idx_t offset) const {
    return get_next_one_offset(offset, size());
  }
  idx_t get_next_zero_offset(idx_t offset) const {
    return get_next_zero_offset(offset, size());
  }

231 232
  // Returns the number of bits set in the bitmap.
  idx_t count_one_bits() const;
D
duke 已提交
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248

  // Set operations.
  void set_union(BitMap bits);
  void set_difference(BitMap bits);
  void set_intersection(BitMap bits);
  // Returns true iff "this" is a superset of "bits".
  bool contains(const BitMap bits) const;
  // Returns true iff "this and "bits" have a non-empty intersection.
  bool intersects(const BitMap bits) const;

  // Returns result of whether this map changed
  // during the operation
  bool set_union_with_result(BitMap bits);
  bool set_difference_with_result(BitMap bits);
  bool set_intersection_with_result(BitMap bits);

249 250 251 252 253 254 255 256 257
  // Requires the submap of "bits" starting at offset to be at least as
  // large as "this".  Modifies "this" to be the intersection of its
  // current contents and the submap of "bits" starting at "offset" of the
  // same length as "this."
  // (For expedience, currently requires the offset to be aligned to the
  // bitsize of a uintptr_t.  This should go away in the future though it
  // will probably remain a good case to optimize.)
  void set_intersection_at_offset(BitMap bits, idx_t offset);

D
duke 已提交
258 259 260 261 262 263 264 265
  void set_from(BitMap bits);

  bool is_same(BitMap bits);

  // Test if all bits are set or cleared
  bool is_full() const;
  bool is_empty() const;

266
  void print_on_error(outputStream* st, const char* prefix) const;
D
duke 已提交
267 268 269 270 271 272 273 274 275 276 277

#ifndef PRODUCT
 public:
  // Printing
  void print_on(outputStream* st) const;
#endif
};

// Convenience class wrapping BitMap which provides multiple bits per slot.
class BitMap2D VALUE_OBJ_CLASS_SPEC {
 public:
278 279 280
  typedef BitMap::idx_t idx_t;          // Type used for bit and word indices.
  typedef BitMap::bm_word_t bm_word_t;  // Element type of array that
                                        // represents the bitmap.
D
duke 已提交
281 282 283 284 285 286 287 288 289 290 291 292 293 294
 private:
  BitMap _map;
  idx_t  _bits_per_slot;

  idx_t bit_index(idx_t slot_index, idx_t bit_within_slot_index) const {
    return slot_index * _bits_per_slot + bit_within_slot_index;
  }

  void verify_bit_within_slot_index(idx_t index) const {
    assert(index < _bits_per_slot, "bit_within_slot index out of bounds");
  }

 public:
  // Construction. bits_per_slot must be greater than 0.
295
  BitMap2D(bm_word_t* map, idx_t size_in_slots, idx_t bits_per_slot);
D
duke 已提交
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339

  // Allocates necessary data structure in resource area. bits_per_slot must be greater than 0.
  BitMap2D(idx_t size_in_slots, idx_t bits_per_slot);

  idx_t size_in_bits() {
    return _map.size();
  }

  // Returns number of full slots that have been allocated
  idx_t size_in_slots() {
    // Round down
    return _map.size() / _bits_per_slot;
  }

  bool 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());
  }

  bool at(idx_t slot_index, idx_t bit_within_slot_index) const {
    verify_bit_within_slot_index(bit_within_slot_index);
    return _map.at(bit_index(slot_index, bit_within_slot_index));
  }

  void set_bit(idx_t slot_index, idx_t bit_within_slot_index) {
    verify_bit_within_slot_index(bit_within_slot_index);
    _map.set_bit(bit_index(slot_index, bit_within_slot_index));
  }

  void clear_bit(idx_t slot_index, idx_t bit_within_slot_index) {
    verify_bit_within_slot_index(bit_within_slot_index);
    _map.clear_bit(bit_index(slot_index, bit_within_slot_index));
  }

  void at_put(idx_t slot_index, idx_t bit_within_slot_index, bool value) {
    verify_bit_within_slot_index(bit_within_slot_index);
    _map.at_put(bit_index(slot_index, bit_within_slot_index), value);
  }

  void at_put_grow(idx_t slot_index, idx_t bit_within_slot_index, bool value) {
    verify_bit_within_slot_index(bit_within_slot_index);
    _map.at_put_grow(bit_index(slot_index, bit_within_slot_index), value);
  }

340
  void clear();
D
duke 已提交
341 342
};

343
// Closure for iterating over BitMaps
D
duke 已提交
344

345 346 347 348 349 350
class BitMapClosure VALUE_OBJ_CLASS_SPEC {
 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;
};
351 352

#endif // SHARE_VM_UTILITIES_BITMAP_HPP