src/share/vm/utilities/bitMap.cpp

Fri, 29 Apr 2016 00:06:10 +0800

author
aoqi
date
Fri, 29 Apr 2016 00:06:10 +0800
changeset 1
2d8a650513c2
parent 0
f90c822e73f8
child 6876
710a3c8b516e
permissions
-rw-r--r--

Added MIPS 64-bit port.

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 #include "precompiled.hpp"
aoqi@0 26 #include "memory/allocation.inline.hpp"
aoqi@0 27 #include "utilities/bitMap.inline.hpp"
aoqi@0 28 #include "utilities/copy.hpp"
aoqi@0 29 #ifdef TARGET_OS_FAMILY_linux
aoqi@0 30 # include "os_linux.inline.hpp"
aoqi@0 31 #endif
aoqi@0 32 #ifdef TARGET_OS_FAMILY_solaris
aoqi@0 33 # include "os_solaris.inline.hpp"
aoqi@0 34 #endif
aoqi@0 35 #ifdef TARGET_OS_FAMILY_windows
aoqi@0 36 # include "os_windows.inline.hpp"
aoqi@0 37 #endif
aoqi@0 38 #ifdef TARGET_OS_FAMILY_aix
aoqi@0 39 # include "os_aix.inline.hpp"
aoqi@0 40 #endif
aoqi@0 41 #ifdef TARGET_OS_FAMILY_bsd
aoqi@0 42 # include "os_bsd.inline.hpp"
aoqi@0 43 #endif
aoqi@0 44
aoqi@0 45
aoqi@0 46 BitMap::BitMap(bm_word_t* map, idx_t size_in_bits) :
aoqi@0 47 _map(map), _size(size_in_bits), _map_allocator(false)
aoqi@0 48 {
aoqi@0 49 assert(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption.");
aoqi@0 50 assert(size_in_bits >= 0, "just checking");
aoqi@0 51 }
aoqi@0 52
aoqi@0 53
aoqi@0 54 BitMap::BitMap(idx_t size_in_bits, bool in_resource_area) :
aoqi@0 55 _map(NULL), _size(0), _map_allocator(false)
aoqi@0 56 {
aoqi@0 57 assert(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption.");
aoqi@0 58 resize(size_in_bits, in_resource_area);
aoqi@0 59 }
aoqi@0 60
aoqi@0 61 void BitMap::resize(idx_t size_in_bits, bool in_resource_area) {
aoqi@0 62 assert(size_in_bits >= 0, "just checking");
aoqi@0 63 idx_t old_size_in_words = size_in_words();
aoqi@0 64 bm_word_t* old_map = map();
aoqi@0 65
aoqi@0 66 _size = size_in_bits;
aoqi@0 67 idx_t new_size_in_words = size_in_words();
aoqi@0 68 if (in_resource_area) {
aoqi@0 69 _map = NEW_RESOURCE_ARRAY(bm_word_t, new_size_in_words);
aoqi@0 70 } else {
aoqi@0 71 if (old_map != NULL) {
aoqi@0 72 _map_allocator.free();
aoqi@0 73 }
aoqi@0 74 _map = _map_allocator.allocate(new_size_in_words);
aoqi@0 75 }
aoqi@0 76 Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) _map,
aoqi@0 77 MIN2(old_size_in_words, new_size_in_words));
aoqi@0 78 if (new_size_in_words > old_size_in_words) {
aoqi@0 79 clear_range_of_words(old_size_in_words, size_in_words());
aoqi@0 80 }
aoqi@0 81 }
aoqi@0 82
aoqi@0 83 void BitMap::set_range_within_word(idx_t beg, idx_t end) {
aoqi@0 84 // With a valid range (beg <= end), this test ensures that end != 0, as
aoqi@0 85 // required by inverted_bit_mask_for_range. Also avoids an unnecessary write.
aoqi@0 86 if (beg != end) {
aoqi@0 87 bm_word_t mask = inverted_bit_mask_for_range(beg, end);
aoqi@0 88 *word_addr(beg) |= ~mask;
aoqi@0 89 }
aoqi@0 90 }
aoqi@0 91
aoqi@0 92 void BitMap::clear_range_within_word(idx_t beg, idx_t end) {
aoqi@0 93 // With a valid range (beg <= end), this test ensures that end != 0, as
aoqi@0 94 // required by inverted_bit_mask_for_range. Also avoids an unnecessary write.
aoqi@0 95 if (beg != end) {
aoqi@0 96 bm_word_t mask = inverted_bit_mask_for_range(beg, end);
aoqi@0 97 *word_addr(beg) &= mask;
aoqi@0 98 }
aoqi@0 99 }
aoqi@0 100
aoqi@0 101 void BitMap::par_put_range_within_word(idx_t beg, idx_t end, bool value) {
aoqi@0 102 assert(value == 0 || value == 1, "0 for clear, 1 for set");
aoqi@0 103 // With a valid range (beg <= end), this test ensures that end != 0, as
aoqi@0 104 // required by inverted_bit_mask_for_range. Also avoids an unnecessary write.
aoqi@0 105 if (beg != end) {
aoqi@0 106 intptr_t* pw = (intptr_t*)word_addr(beg);
aoqi@0 107 intptr_t w = *pw;
aoqi@0 108 intptr_t mr = (intptr_t)inverted_bit_mask_for_range(beg, end);
aoqi@0 109 intptr_t nw = value ? (w | ~mr) : (w & mr);
aoqi@0 110 while (true) {
aoqi@0 111 intptr_t res = Atomic::cmpxchg_ptr(nw, pw, w);
aoqi@0 112 if (res == w) break;
aoqi@0 113 w = res;
aoqi@0 114 nw = value ? (w | ~mr) : (w & mr);
aoqi@0 115 }
aoqi@0 116 }
aoqi@0 117 }
aoqi@0 118
aoqi@0 119 void BitMap::set_range(idx_t beg, idx_t end) {
aoqi@0 120 verify_range(beg, end);
aoqi@0 121
aoqi@0 122 idx_t beg_full_word = word_index_round_up(beg);
aoqi@0 123 idx_t end_full_word = word_index(end);
aoqi@0 124
aoqi@0 125 if (beg_full_word < end_full_word) {
aoqi@0 126 // The range includes at least one full word.
aoqi@0 127 set_range_within_word(beg, bit_index(beg_full_word));
aoqi@0 128 set_range_of_words(beg_full_word, end_full_word);
aoqi@0 129 set_range_within_word(bit_index(end_full_word), end);
aoqi@0 130 } else {
aoqi@0 131 // The range spans at most 2 partial words.
aoqi@0 132 idx_t boundary = MIN2(bit_index(beg_full_word), end);
aoqi@0 133 set_range_within_word(beg, boundary);
aoqi@0 134 set_range_within_word(boundary, end);
aoqi@0 135 }
aoqi@0 136 }
aoqi@0 137
aoqi@0 138 void BitMap::clear_range(idx_t beg, idx_t end) {
aoqi@0 139 verify_range(beg, end);
aoqi@0 140
aoqi@0 141 idx_t beg_full_word = word_index_round_up(beg);
aoqi@0 142 idx_t end_full_word = word_index(end);
aoqi@0 143
aoqi@0 144 if (beg_full_word < end_full_word) {
aoqi@0 145 // The range includes at least one full word.
aoqi@0 146 clear_range_within_word(beg, bit_index(beg_full_word));
aoqi@0 147 clear_range_of_words(beg_full_word, end_full_word);
aoqi@0 148 clear_range_within_word(bit_index(end_full_word), end);
aoqi@0 149 } else {
aoqi@0 150 // The range spans at most 2 partial words.
aoqi@0 151 idx_t boundary = MIN2(bit_index(beg_full_word), end);
aoqi@0 152 clear_range_within_word(beg, boundary);
aoqi@0 153 clear_range_within_word(boundary, end);
aoqi@0 154 }
aoqi@0 155 }
aoqi@0 156
aoqi@0 157 void BitMap::set_large_range(idx_t beg, idx_t end) {
aoqi@0 158 verify_range(beg, end);
aoqi@0 159
aoqi@0 160 idx_t beg_full_word = word_index_round_up(beg);
aoqi@0 161 idx_t end_full_word = word_index(end);
aoqi@0 162
aoqi@0 163 assert(end_full_word - beg_full_word >= 32,
aoqi@0 164 "the range must include at least 32 bytes");
aoqi@0 165
aoqi@0 166 // The range includes at least one full word.
aoqi@0 167 set_range_within_word(beg, bit_index(beg_full_word));
aoqi@0 168 set_large_range_of_words(beg_full_word, end_full_word);
aoqi@0 169 set_range_within_word(bit_index(end_full_word), end);
aoqi@0 170 }
aoqi@0 171
aoqi@0 172 void BitMap::clear_large_range(idx_t beg, idx_t end) {
aoqi@0 173 verify_range(beg, end);
aoqi@0 174
aoqi@0 175 idx_t beg_full_word = word_index_round_up(beg);
aoqi@0 176 idx_t end_full_word = word_index(end);
aoqi@0 177
aoqi@0 178 assert(end_full_word - beg_full_word >= 32,
aoqi@0 179 "the range must include at least 32 bytes");
aoqi@0 180
aoqi@0 181 // The range includes at least one full word.
aoqi@0 182 clear_range_within_word(beg, bit_index(beg_full_word));
aoqi@0 183 clear_large_range_of_words(beg_full_word, end_full_word);
aoqi@0 184 clear_range_within_word(bit_index(end_full_word), end);
aoqi@0 185 }
aoqi@0 186
aoqi@0 187 void BitMap::at_put(idx_t offset, bool value) {
aoqi@0 188 if (value) {
aoqi@0 189 set_bit(offset);
aoqi@0 190 } else {
aoqi@0 191 clear_bit(offset);
aoqi@0 192 }
aoqi@0 193 }
aoqi@0 194
aoqi@0 195 // Return true to indicate that this thread changed
aoqi@0 196 // the bit, false to indicate that someone else did.
aoqi@0 197 // In either case, the requested bit is in the
aoqi@0 198 // requested state some time during the period that
aoqi@0 199 // this thread is executing this call. More importantly,
aoqi@0 200 // if no other thread is executing an action to
aoqi@0 201 // change the requested bit to a state other than
aoqi@0 202 // the one that this thread is trying to set it to,
aoqi@0 203 // then the the bit is in the expected state
aoqi@0 204 // at exit from this method. However, rather than
aoqi@0 205 // make such a strong assertion here, based on
aoqi@0 206 // assuming such constrained use (which though true
aoqi@0 207 // today, could change in the future to service some
aoqi@0 208 // funky parallel algorithm), we encourage callers
aoqi@0 209 // to do such verification, as and when appropriate.
aoqi@0 210 bool BitMap::par_at_put(idx_t bit, bool value) {
aoqi@0 211 return value ? par_set_bit(bit) : par_clear_bit(bit);
aoqi@0 212 }
aoqi@0 213
aoqi@0 214 void BitMap::at_put_grow(idx_t offset, bool value) {
aoqi@0 215 if (offset >= size()) {
aoqi@0 216 resize(2 * MAX2(size(), offset));
aoqi@0 217 }
aoqi@0 218 at_put(offset, value);
aoqi@0 219 }
aoqi@0 220
aoqi@0 221 void BitMap::at_put_range(idx_t start_offset, idx_t end_offset, bool value) {
aoqi@0 222 if (value) {
aoqi@0 223 set_range(start_offset, end_offset);
aoqi@0 224 } else {
aoqi@0 225 clear_range(start_offset, end_offset);
aoqi@0 226 }
aoqi@0 227 }
aoqi@0 228
aoqi@0 229 void BitMap::par_at_put_range(idx_t beg, idx_t end, bool value) {
aoqi@0 230 verify_range(beg, end);
aoqi@0 231
aoqi@0 232 idx_t beg_full_word = word_index_round_up(beg);
aoqi@0 233 idx_t end_full_word = word_index(end);
aoqi@0 234
aoqi@0 235 if (beg_full_word < end_full_word) {
aoqi@0 236 // The range includes at least one full word.
aoqi@0 237 par_put_range_within_word(beg, bit_index(beg_full_word), value);
aoqi@0 238 if (value) {
aoqi@0 239 set_range_of_words(beg_full_word, end_full_word);
aoqi@0 240 } else {
aoqi@0 241 clear_range_of_words(beg_full_word, end_full_word);
aoqi@0 242 }
aoqi@0 243 par_put_range_within_word(bit_index(end_full_word), end, value);
aoqi@0 244 } else {
aoqi@0 245 // The range spans at most 2 partial words.
aoqi@0 246 idx_t boundary = MIN2(bit_index(beg_full_word), end);
aoqi@0 247 par_put_range_within_word(beg, boundary, value);
aoqi@0 248 par_put_range_within_word(boundary, end, value);
aoqi@0 249 }
aoqi@0 250
aoqi@0 251 }
aoqi@0 252
aoqi@0 253 void BitMap::at_put_large_range(idx_t beg, idx_t end, bool value) {
aoqi@0 254 if (value) {
aoqi@0 255 set_large_range(beg, end);
aoqi@0 256 } else {
aoqi@0 257 clear_large_range(beg, end);
aoqi@0 258 }
aoqi@0 259 }
aoqi@0 260
aoqi@0 261 void BitMap::par_at_put_large_range(idx_t beg, idx_t end, bool value) {
aoqi@0 262 verify_range(beg, end);
aoqi@0 263
aoqi@0 264 idx_t beg_full_word = word_index_round_up(beg);
aoqi@0 265 idx_t end_full_word = word_index(end);
aoqi@0 266
aoqi@0 267 assert(end_full_word - beg_full_word >= 32,
aoqi@0 268 "the range must include at least 32 bytes");
aoqi@0 269
aoqi@0 270 // The range includes at least one full word.
aoqi@0 271 par_put_range_within_word(beg, bit_index(beg_full_word), value);
aoqi@0 272 if (value) {
aoqi@0 273 set_large_range_of_words(beg_full_word, end_full_word);
aoqi@0 274 } else {
aoqi@0 275 clear_large_range_of_words(beg_full_word, end_full_word);
aoqi@0 276 }
aoqi@0 277 par_put_range_within_word(bit_index(end_full_word), end, value);
aoqi@0 278 }
aoqi@0 279
aoqi@0 280 bool BitMap::contains(const BitMap other) const {
aoqi@0 281 assert(size() == other.size(), "must have same size");
aoqi@0 282 bm_word_t* dest_map = map();
aoqi@0 283 bm_word_t* other_map = other.map();
aoqi@0 284 idx_t size = size_in_words();
aoqi@0 285 for (idx_t index = 0; index < size_in_words(); index++) {
aoqi@0 286 bm_word_t word_union = dest_map[index] | other_map[index];
aoqi@0 287 // If this has more bits set than dest_map[index], then other is not a
aoqi@0 288 // subset.
aoqi@0 289 if (word_union != dest_map[index]) return false;
aoqi@0 290 }
aoqi@0 291 return true;
aoqi@0 292 }
aoqi@0 293
aoqi@0 294 bool BitMap::intersects(const BitMap other) const {
aoqi@0 295 assert(size() == other.size(), "must have same size");
aoqi@0 296 bm_word_t* dest_map = map();
aoqi@0 297 bm_word_t* other_map = other.map();
aoqi@0 298 idx_t size = size_in_words();
aoqi@0 299 for (idx_t index = 0; index < size_in_words(); index++) {
aoqi@0 300 if ((dest_map[index] & other_map[index]) != 0) return true;
aoqi@0 301 }
aoqi@0 302 // Otherwise, no intersection.
aoqi@0 303 return false;
aoqi@0 304 }
aoqi@0 305
aoqi@0 306 void BitMap::set_union(BitMap other) {
aoqi@0 307 assert(size() == other.size(), "must have same size");
aoqi@0 308 bm_word_t* dest_map = map();
aoqi@0 309 bm_word_t* other_map = other.map();
aoqi@0 310 idx_t size = size_in_words();
aoqi@0 311 for (idx_t index = 0; index < size_in_words(); index++) {
aoqi@0 312 dest_map[index] = dest_map[index] | other_map[index];
aoqi@0 313 }
aoqi@0 314 }
aoqi@0 315
aoqi@0 316
aoqi@0 317 void BitMap::set_difference(BitMap other) {
aoqi@0 318 assert(size() == other.size(), "must have same size");
aoqi@0 319 bm_word_t* dest_map = map();
aoqi@0 320 bm_word_t* other_map = other.map();
aoqi@0 321 idx_t size = size_in_words();
aoqi@0 322 for (idx_t index = 0; index < size_in_words(); index++) {
aoqi@0 323 dest_map[index] = dest_map[index] & ~(other_map[index]);
aoqi@0 324 }
aoqi@0 325 }
aoqi@0 326
aoqi@0 327
aoqi@0 328 void BitMap::set_intersection(BitMap other) {
aoqi@0 329 assert(size() == other.size(), "must have same size");
aoqi@0 330 bm_word_t* dest_map = map();
aoqi@0 331 bm_word_t* other_map = other.map();
aoqi@0 332 idx_t size = size_in_words();
aoqi@0 333 for (idx_t index = 0; index < size; index++) {
aoqi@0 334 dest_map[index] = dest_map[index] & other_map[index];
aoqi@0 335 }
aoqi@0 336 }
aoqi@0 337
aoqi@0 338
aoqi@0 339 void BitMap::set_intersection_at_offset(BitMap other, idx_t offset) {
aoqi@0 340 assert(other.size() >= offset, "offset not in range");
aoqi@0 341 assert(other.size() - offset >= size(), "other not large enough");
aoqi@0 342 // XXX Ideally, we would remove this restriction.
aoqi@0 343 guarantee((offset % (sizeof(bm_word_t) * BitsPerByte)) == 0,
aoqi@0 344 "Only handle aligned cases so far.");
aoqi@0 345 bm_word_t* dest_map = map();
aoqi@0 346 bm_word_t* other_map = other.map();
aoqi@0 347 idx_t offset_word_ind = word_index(offset);
aoqi@0 348 idx_t size = size_in_words();
aoqi@0 349 for (idx_t index = 0; index < size; index++) {
aoqi@0 350 dest_map[index] = dest_map[index] & other_map[offset_word_ind + index];
aoqi@0 351 }
aoqi@0 352 }
aoqi@0 353
aoqi@0 354 bool BitMap::set_union_with_result(BitMap other) {
aoqi@0 355 assert(size() == other.size(), "must have same size");
aoqi@0 356 bool changed = false;
aoqi@0 357 bm_word_t* dest_map = map();
aoqi@0 358 bm_word_t* other_map = other.map();
aoqi@0 359 idx_t size = size_in_words();
aoqi@0 360 for (idx_t index = 0; index < size; index++) {
aoqi@0 361 idx_t temp = map(index) | other_map[index];
aoqi@0 362 changed = changed || (temp != map(index));
aoqi@0 363 map()[index] = temp;
aoqi@0 364 }
aoqi@0 365 return changed;
aoqi@0 366 }
aoqi@0 367
aoqi@0 368
aoqi@0 369 bool BitMap::set_difference_with_result(BitMap other) {
aoqi@0 370 assert(size() == other.size(), "must have same size");
aoqi@0 371 bool changed = false;
aoqi@0 372 bm_word_t* dest_map = map();
aoqi@0 373 bm_word_t* other_map = other.map();
aoqi@0 374 idx_t size = size_in_words();
aoqi@0 375 for (idx_t index = 0; index < size; index++) {
aoqi@0 376 bm_word_t temp = dest_map[index] & ~(other_map[index]);
aoqi@0 377 changed = changed || (temp != dest_map[index]);
aoqi@0 378 dest_map[index] = temp;
aoqi@0 379 }
aoqi@0 380 return changed;
aoqi@0 381 }
aoqi@0 382
aoqi@0 383
aoqi@0 384 bool BitMap::set_intersection_with_result(BitMap other) {
aoqi@0 385 assert(size() == other.size(), "must have same size");
aoqi@0 386 bool changed = false;
aoqi@0 387 bm_word_t* dest_map = map();
aoqi@0 388 bm_word_t* other_map = other.map();
aoqi@0 389 idx_t size = size_in_words();
aoqi@0 390 for (idx_t index = 0; index < size; index++) {
aoqi@0 391 bm_word_t orig = dest_map[index];
aoqi@0 392 bm_word_t temp = orig & other_map[index];
aoqi@0 393 changed = changed || (temp != orig);
aoqi@0 394 dest_map[index] = temp;
aoqi@0 395 }
aoqi@0 396 return changed;
aoqi@0 397 }
aoqi@0 398
aoqi@0 399
aoqi@0 400 void BitMap::set_from(BitMap other) {
aoqi@0 401 assert(size() == other.size(), "must have same size");
aoqi@0 402 bm_word_t* dest_map = map();
aoqi@0 403 bm_word_t* other_map = other.map();
aoqi@0 404 idx_t size = size_in_words();
aoqi@0 405 for (idx_t index = 0; index < size; index++) {
aoqi@0 406 dest_map[index] = other_map[index];
aoqi@0 407 }
aoqi@0 408 }
aoqi@0 409
aoqi@0 410
aoqi@0 411 bool BitMap::is_same(BitMap other) {
aoqi@0 412 assert(size() == other.size(), "must have same size");
aoqi@0 413 bm_word_t* dest_map = map();
aoqi@0 414 bm_word_t* other_map = other.map();
aoqi@0 415 idx_t size = size_in_words();
aoqi@0 416 for (idx_t index = 0; index < size; index++) {
aoqi@0 417 if (dest_map[index] != other_map[index]) return false;
aoqi@0 418 }
aoqi@0 419 return true;
aoqi@0 420 }
aoqi@0 421
aoqi@0 422 bool BitMap::is_full() const {
aoqi@0 423 bm_word_t* word = map();
aoqi@0 424 idx_t rest = size();
aoqi@0 425 for (; rest >= (idx_t) BitsPerWord; rest -= BitsPerWord) {
aoqi@0 426 if (*word != (bm_word_t) AllBits) return false;
aoqi@0 427 word++;
aoqi@0 428 }
aoqi@0 429 return rest == 0 || (*word | ~right_n_bits((int)rest)) == (bm_word_t) AllBits;
aoqi@0 430 }
aoqi@0 431
aoqi@0 432
aoqi@0 433 bool BitMap::is_empty() const {
aoqi@0 434 bm_word_t* word = map();
aoqi@0 435 idx_t rest = size();
aoqi@0 436 for (; rest >= (idx_t) BitsPerWord; rest -= BitsPerWord) {
aoqi@0 437 if (*word != (bm_word_t) NoBits) return false;
aoqi@0 438 word++;
aoqi@0 439 }
aoqi@0 440 return rest == 0 || (*word & right_n_bits((int)rest)) == (bm_word_t) NoBits;
aoqi@0 441 }
aoqi@0 442
aoqi@0 443 void BitMap::clear_large() {
aoqi@0 444 clear_large_range_of_words(0, size_in_words());
aoqi@0 445 }
aoqi@0 446
aoqi@0 447 // Note that if the closure itself modifies the bitmap
aoqi@0 448 // then modifications in and to the left of the _bit_ being
aoqi@0 449 // currently sampled will not be seen. Note also that the
aoqi@0 450 // interval [leftOffset, rightOffset) is right open.
aoqi@0 451 bool BitMap::iterate(BitMapClosure* blk, idx_t leftOffset, idx_t rightOffset) {
aoqi@0 452 verify_range(leftOffset, rightOffset);
aoqi@0 453
aoqi@0 454 idx_t startIndex = word_index(leftOffset);
aoqi@0 455 idx_t endIndex = MIN2(word_index(rightOffset) + 1, size_in_words());
aoqi@0 456 for (idx_t index = startIndex, offset = leftOffset;
aoqi@0 457 offset < rightOffset && index < endIndex;
aoqi@0 458 offset = (++index) << LogBitsPerWord) {
aoqi@0 459 idx_t rest = map(index) >> (offset & (BitsPerWord - 1));
aoqi@0 460 for (; offset < rightOffset && rest != (bm_word_t)NoBits; offset++) {
aoqi@0 461 if (rest & 1) {
aoqi@0 462 if (!blk->do_bit(offset)) return false;
aoqi@0 463 // resample at each closure application
aoqi@0 464 // (see, for instance, CMS bug 4525989)
aoqi@0 465 rest = map(index) >> (offset & (BitsPerWord -1));
aoqi@0 466 }
aoqi@0 467 rest = rest >> 1;
aoqi@0 468 }
aoqi@0 469 }
aoqi@0 470 return true;
aoqi@0 471 }
aoqi@0 472
aoqi@0 473 BitMap::idx_t* BitMap::_pop_count_table = NULL;
aoqi@0 474
aoqi@0 475 void BitMap::init_pop_count_table() {
aoqi@0 476 if (_pop_count_table == NULL) {
aoqi@0 477 BitMap::idx_t *table = NEW_C_HEAP_ARRAY(idx_t, 256, mtInternal);
aoqi@0 478 for (uint i = 0; i < 256; i++) {
aoqi@0 479 table[i] = num_set_bits(i);
aoqi@0 480 }
aoqi@0 481
aoqi@0 482 intptr_t res = Atomic::cmpxchg_ptr((intptr_t) table,
aoqi@0 483 (intptr_t*) &_pop_count_table,
aoqi@0 484 (intptr_t) NULL_WORD);
aoqi@0 485 if (res != NULL_WORD) {
aoqi@0 486 guarantee( _pop_count_table == (void*) res, "invariant" );
aoqi@0 487 FREE_C_HEAP_ARRAY(bm_word_t, table, mtInternal);
aoqi@0 488 }
aoqi@0 489 }
aoqi@0 490 }
aoqi@0 491
aoqi@0 492 BitMap::idx_t BitMap::num_set_bits(bm_word_t w) {
aoqi@0 493 idx_t bits = 0;
aoqi@0 494
aoqi@0 495 while (w != 0) {
aoqi@0 496 while ((w & 1) == 0) {
aoqi@0 497 w >>= 1;
aoqi@0 498 }
aoqi@0 499 bits++;
aoqi@0 500 w >>= 1;
aoqi@0 501 }
aoqi@0 502 return bits;
aoqi@0 503 }
aoqi@0 504
aoqi@0 505 BitMap::idx_t BitMap::num_set_bits_from_table(unsigned char c) {
aoqi@0 506 assert(_pop_count_table != NULL, "precondition");
aoqi@0 507 return _pop_count_table[c];
aoqi@0 508 }
aoqi@0 509
aoqi@0 510 BitMap::idx_t BitMap::count_one_bits() const {
aoqi@0 511 init_pop_count_table(); // If necessary.
aoqi@0 512 idx_t sum = 0;
aoqi@0 513 typedef unsigned char uchar;
aoqi@0 514 for (idx_t i = 0; i < size_in_words(); i++) {
aoqi@0 515 bm_word_t w = map()[i];
aoqi@0 516 for (size_t j = 0; j < sizeof(bm_word_t); j++) {
aoqi@0 517 sum += num_set_bits_from_table(uchar(w & 255));
aoqi@0 518 w >>= 8;
aoqi@0 519 }
aoqi@0 520 }
aoqi@0 521 return sum;
aoqi@0 522 }
aoqi@0 523
aoqi@0 524 void BitMap::print_on_error(outputStream* st, const char* prefix) const {
aoqi@0 525 st->print_cr("%s[" PTR_FORMAT ", " PTR_FORMAT ")",
aoqi@0 526 prefix, p2i(map()), p2i((char*)map() + (size() >> LogBitsPerByte)));
aoqi@0 527 }
aoqi@0 528
aoqi@0 529 #ifndef PRODUCT
aoqi@0 530
aoqi@0 531 void BitMap::print_on(outputStream* st) const {
aoqi@0 532 tty->print("Bitmap(" SIZE_FORMAT "):", size());
aoqi@0 533 for (idx_t index = 0; index < size(); index++) {
aoqi@0 534 tty->print("%c", at(index) ? '1' : '0');
aoqi@0 535 }
aoqi@0 536 tty->cr();
aoqi@0 537 }
aoqi@0 538
aoqi@0 539 #endif
aoqi@0 540
aoqi@0 541
aoqi@0 542 BitMap2D::BitMap2D(bm_word_t* map, idx_t size_in_slots, idx_t bits_per_slot)
aoqi@0 543 : _bits_per_slot(bits_per_slot)
aoqi@0 544 , _map(map, size_in_slots * bits_per_slot)
aoqi@0 545 {
aoqi@0 546 }
aoqi@0 547
aoqi@0 548
aoqi@0 549 BitMap2D::BitMap2D(idx_t size_in_slots, idx_t bits_per_slot)
aoqi@0 550 : _bits_per_slot(bits_per_slot)
aoqi@0 551 , _map(size_in_slots * bits_per_slot)
aoqi@0 552 {
aoqi@0 553 }

mercurial