src/share/vm/utilities/bitMap.cpp

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
duke@435 25 # include "incls/_precompiled.incl"
duke@435 26 # include "incls/_bitMap.cpp.incl"
duke@435 27
duke@435 28
ysr@777 29 BitMap::BitMap(bm_word_t* map, idx_t size_in_bits) :
ysr@777 30 _map(map), _size(size_in_bits)
ysr@777 31 {
ysr@777 32 assert(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption.");
duke@435 33 assert(size_in_bits >= 0, "just checking");
duke@435 34 }
duke@435 35
duke@435 36
ysr@777 37 BitMap::BitMap(idx_t size_in_bits, bool in_resource_area) :
ysr@777 38 _map(NULL), _size(0)
ysr@777 39 {
ysr@777 40 assert(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption.");
ysr@777 41 resize(size_in_bits, in_resource_area);
duke@435 42 }
duke@435 43
duke@435 44
ysr@777 45 void BitMap::verify_index(idx_t index) const {
ysr@777 46 assert(index < _size, "BitMap index out of bounds");
ysr@777 47 }
ysr@777 48
ysr@777 49 void BitMap::verify_range(idx_t beg_index, idx_t end_index) const {
ysr@777 50 #ifdef ASSERT
ysr@777 51 assert(beg_index <= end_index, "BitMap range error");
ysr@777 52 // Note that [0,0) and [size,size) are both valid ranges.
ysr@777 53 if (end_index != _size) verify_index(end_index);
ysr@777 54 #endif
ysr@777 55 }
ysr@777 56
ysr@777 57 void BitMap::resize(idx_t size_in_bits, bool in_resource_area) {
duke@435 58 assert(size_in_bits >= 0, "just checking");
ysr@777 59 idx_t old_size_in_words = size_in_words();
ysr@777 60 bm_word_t* old_map = map();
ysr@777 61
duke@435 62 _size = size_in_bits;
ysr@777 63 idx_t new_size_in_words = size_in_words();
ysr@777 64 if (in_resource_area) {
ysr@777 65 _map = NEW_RESOURCE_ARRAY(bm_word_t, new_size_in_words);
ysr@777 66 } else {
ysr@777 67 if (old_map != NULL) FREE_C_HEAP_ARRAY(bm_word_t, _map);
ysr@777 68 _map = NEW_C_HEAP_ARRAY(bm_word_t, new_size_in_words);
ysr@777 69 }
ysr@777 70 Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) _map,
ysr@777 71 MIN2(old_size_in_words, new_size_in_words));
duke@435 72 if (new_size_in_words > old_size_in_words) {
duke@435 73 clear_range_of_words(old_size_in_words, size_in_words());
duke@435 74 }
duke@435 75 }
duke@435 76
duke@435 77 void BitMap::set_range_within_word(idx_t beg, idx_t end) {
duke@435 78 // With a valid range (beg <= end), this test ensures that end != 0, as
duke@435 79 // required by inverted_bit_mask_for_range. Also avoids an unnecessary write.
duke@435 80 if (beg != end) {
ysr@777 81 bm_word_t mask = inverted_bit_mask_for_range(beg, end);
duke@435 82 *word_addr(beg) |= ~mask;
duke@435 83 }
duke@435 84 }
duke@435 85
duke@435 86 void BitMap::clear_range_within_word(idx_t beg, idx_t end) {
duke@435 87 // With a valid range (beg <= end), this test ensures that end != 0, as
duke@435 88 // required by inverted_bit_mask_for_range. Also avoids an unnecessary write.
duke@435 89 if (beg != end) {
ysr@777 90 bm_word_t mask = inverted_bit_mask_for_range(beg, end);
duke@435 91 *word_addr(beg) &= mask;
duke@435 92 }
duke@435 93 }
duke@435 94
duke@435 95 void BitMap::par_put_range_within_word(idx_t beg, idx_t end, bool value) {
duke@435 96 assert(value == 0 || value == 1, "0 for clear, 1 for set");
duke@435 97 // With a valid range (beg <= end), this test ensures that end != 0, as
duke@435 98 // required by inverted_bit_mask_for_range. Also avoids an unnecessary write.
duke@435 99 if (beg != end) {
duke@435 100 intptr_t* pw = (intptr_t*)word_addr(beg);
duke@435 101 intptr_t w = *pw;
duke@435 102 intptr_t mr = (intptr_t)inverted_bit_mask_for_range(beg, end);
duke@435 103 intptr_t nw = value ? (w | ~mr) : (w & mr);
duke@435 104 while (true) {
duke@435 105 intptr_t res = Atomic::cmpxchg_ptr(nw, pw, w);
duke@435 106 if (res == w) break;
duke@435 107 w = *pw;
duke@435 108 nw = value ? (w | ~mr) : (w & mr);
duke@435 109 }
duke@435 110 }
duke@435 111 }
duke@435 112
duke@435 113 void BitMap::set_range(idx_t beg, idx_t end) {
duke@435 114 verify_range(beg, end);
duke@435 115
duke@435 116 idx_t beg_full_word = word_index_round_up(beg);
duke@435 117 idx_t end_full_word = word_index(end);
duke@435 118
duke@435 119 if (beg_full_word < end_full_word) {
duke@435 120 // The range includes at least one full word.
duke@435 121 set_range_within_word(beg, bit_index(beg_full_word));
duke@435 122 set_range_of_words(beg_full_word, end_full_word);
duke@435 123 set_range_within_word(bit_index(end_full_word), end);
duke@435 124 } else {
duke@435 125 // The range spans at most 2 partial words.
duke@435 126 idx_t boundary = MIN2(bit_index(beg_full_word), end);
duke@435 127 set_range_within_word(beg, boundary);
duke@435 128 set_range_within_word(boundary, end);
duke@435 129 }
duke@435 130 }
duke@435 131
duke@435 132 void BitMap::clear_range(idx_t beg, idx_t end) {
duke@435 133 verify_range(beg, end);
duke@435 134
duke@435 135 idx_t beg_full_word = word_index_round_up(beg);
duke@435 136 idx_t end_full_word = word_index(end);
duke@435 137
duke@435 138 if (beg_full_word < end_full_word) {
duke@435 139 // The range includes at least one full word.
duke@435 140 clear_range_within_word(beg, bit_index(beg_full_word));
duke@435 141 clear_range_of_words(beg_full_word, end_full_word);
duke@435 142 clear_range_within_word(bit_index(end_full_word), end);
duke@435 143 } else {
duke@435 144 // The range spans at most 2 partial words.
duke@435 145 idx_t boundary = MIN2(bit_index(beg_full_word), end);
duke@435 146 clear_range_within_word(beg, boundary);
duke@435 147 clear_range_within_word(boundary, end);
duke@435 148 }
duke@435 149 }
duke@435 150
duke@435 151 void BitMap::set_large_range(idx_t beg, idx_t end) {
duke@435 152 verify_range(beg, end);
duke@435 153
duke@435 154 idx_t beg_full_word = word_index_round_up(beg);
duke@435 155 idx_t end_full_word = word_index(end);
duke@435 156
duke@435 157 assert(end_full_word - beg_full_word >= 32,
duke@435 158 "the range must include at least 32 bytes");
duke@435 159
duke@435 160 // The range includes at least one full word.
duke@435 161 set_range_within_word(beg, bit_index(beg_full_word));
duke@435 162 set_large_range_of_words(beg_full_word, end_full_word);
duke@435 163 set_range_within_word(bit_index(end_full_word), end);
duke@435 164 }
duke@435 165
duke@435 166 void BitMap::clear_large_range(idx_t beg, idx_t end) {
duke@435 167 verify_range(beg, end);
duke@435 168
duke@435 169 idx_t beg_full_word = word_index_round_up(beg);
duke@435 170 idx_t end_full_word = word_index(end);
duke@435 171
duke@435 172 assert(end_full_word - beg_full_word >= 32,
duke@435 173 "the range must include at least 32 bytes");
duke@435 174
duke@435 175 // The range includes at least one full word.
duke@435 176 clear_range_within_word(beg, bit_index(beg_full_word));
duke@435 177 clear_large_range_of_words(beg_full_word, end_full_word);
duke@435 178 clear_range_within_word(bit_index(end_full_word), end);
duke@435 179 }
duke@435 180
ysr@777 181 void BitMap::mostly_disjoint_range_union(BitMap* from_bitmap,
ysr@777 182 idx_t from_start_index,
ysr@777 183 idx_t to_start_index,
ysr@777 184 size_t word_num) {
ysr@777 185 // Ensure that the parameters are correct.
ysr@777 186 // These shouldn't be that expensive to check, hence I left them as
ysr@777 187 // guarantees.
ysr@777 188 guarantee(from_bitmap->bit_in_word(from_start_index) == 0,
ysr@777 189 "it should be aligned on a word boundary");
ysr@777 190 guarantee(bit_in_word(to_start_index) == 0,
ysr@777 191 "it should be aligned on a word boundary");
ysr@777 192 guarantee(word_num >= 2, "word_num should be at least 2");
ysr@777 193
ysr@777 194 intptr_t* from = (intptr_t*) from_bitmap->word_addr(from_start_index);
ysr@777 195 intptr_t* to = (intptr_t*) word_addr(to_start_index);
ysr@777 196
ysr@777 197 if (*from != 0) {
ysr@777 198 // if it's 0, then there's no point in doing the CAS
ysr@777 199 while (true) {
ysr@777 200 intptr_t old_value = *to;
ysr@777 201 intptr_t new_value = old_value | *from;
ysr@777 202 intptr_t res = Atomic::cmpxchg_ptr(new_value, to, old_value);
ysr@777 203 if (res == old_value) break;
ysr@777 204 }
ysr@777 205 }
ysr@777 206 ++from;
ysr@777 207 ++to;
ysr@777 208
ysr@777 209 for (size_t i = 0; i < word_num - 2; ++i) {
ysr@777 210 if (*from != 0) {
ysr@777 211 // if it's 0, then there's no point in doing the CAS
ysr@777 212 assert(*to == 0, "nobody else should be writing here");
ysr@777 213 intptr_t new_value = *from;
ysr@777 214 *to = new_value;
ysr@777 215 }
ysr@777 216
ysr@777 217 ++from;
ysr@777 218 ++to;
ysr@777 219 }
ysr@777 220
ysr@777 221 if (*from != 0) {
ysr@777 222 // if it's 0, then there's no point in doing the CAS
ysr@777 223 while (true) {
ysr@777 224 intptr_t old_value = *to;
ysr@777 225 intptr_t new_value = old_value | *from;
ysr@777 226 intptr_t res = Atomic::cmpxchg_ptr(new_value, to, old_value);
ysr@777 227 if (res == old_value) break;
ysr@777 228 }
ysr@777 229 }
ysr@777 230
ysr@777 231 // the -1 is because we didn't advance them after the final CAS
ysr@777 232 assert(from ==
ysr@777 233 (intptr_t*) from_bitmap->word_addr(from_start_index) + word_num - 1,
ysr@777 234 "invariant");
ysr@777 235 assert(to == (intptr_t*) word_addr(to_start_index) + word_num - 1,
ysr@777 236 "invariant");
ysr@777 237 }
ysr@777 238
duke@435 239 void BitMap::at_put(idx_t offset, bool value) {
duke@435 240 if (value) {
duke@435 241 set_bit(offset);
duke@435 242 } else {
duke@435 243 clear_bit(offset);
duke@435 244 }
duke@435 245 }
duke@435 246
duke@435 247 // Return true to indicate that this thread changed
duke@435 248 // the bit, false to indicate that someone else did.
duke@435 249 // In either case, the requested bit is in the
duke@435 250 // requested state some time during the period that
duke@435 251 // this thread is executing this call. More importantly,
duke@435 252 // if no other thread is executing an action to
duke@435 253 // change the requested bit to a state other than
duke@435 254 // the one that this thread is trying to set it to,
duke@435 255 // then the the bit is in the expected state
duke@435 256 // at exit from this method. However, rather than
duke@435 257 // make such a strong assertion here, based on
duke@435 258 // assuming such constrained use (which though true
duke@435 259 // today, could change in the future to service some
duke@435 260 // funky parallel algorithm), we encourage callers
duke@435 261 // to do such verification, as and when appropriate.
duke@435 262 bool BitMap::par_at_put(idx_t bit, bool value) {
duke@435 263 return value ? par_set_bit(bit) : par_clear_bit(bit);
duke@435 264 }
duke@435 265
duke@435 266 void BitMap::at_put_grow(idx_t offset, bool value) {
duke@435 267 if (offset >= size()) {
duke@435 268 resize(2 * MAX2(size(), offset));
duke@435 269 }
duke@435 270 at_put(offset, value);
duke@435 271 }
duke@435 272
duke@435 273 void BitMap::at_put_range(idx_t start_offset, idx_t end_offset, bool value) {
duke@435 274 if (value) {
duke@435 275 set_range(start_offset, end_offset);
duke@435 276 } else {
duke@435 277 clear_range(start_offset, end_offset);
duke@435 278 }
duke@435 279 }
duke@435 280
duke@435 281 void BitMap::par_at_put_range(idx_t beg, idx_t end, bool value) {
duke@435 282 verify_range(beg, end);
duke@435 283
duke@435 284 idx_t beg_full_word = word_index_round_up(beg);
duke@435 285 idx_t end_full_word = word_index(end);
duke@435 286
duke@435 287 if (beg_full_word < end_full_word) {
duke@435 288 // The range includes at least one full word.
duke@435 289 par_put_range_within_word(beg, bit_index(beg_full_word), value);
duke@435 290 if (value) {
duke@435 291 set_range_of_words(beg_full_word, end_full_word);
duke@435 292 } else {
duke@435 293 clear_range_of_words(beg_full_word, end_full_word);
duke@435 294 }
duke@435 295 par_put_range_within_word(bit_index(end_full_word), end, value);
duke@435 296 } else {
duke@435 297 // The range spans at most 2 partial words.
duke@435 298 idx_t boundary = MIN2(bit_index(beg_full_word), end);
duke@435 299 par_put_range_within_word(beg, boundary, value);
duke@435 300 par_put_range_within_word(boundary, end, value);
duke@435 301 }
duke@435 302
duke@435 303 }
duke@435 304
duke@435 305 void BitMap::at_put_large_range(idx_t beg, idx_t end, bool value) {
duke@435 306 if (value) {
duke@435 307 set_large_range(beg, end);
duke@435 308 } else {
duke@435 309 clear_large_range(beg, end);
duke@435 310 }
duke@435 311 }
duke@435 312
duke@435 313 void BitMap::par_at_put_large_range(idx_t beg, idx_t end, bool value) {
duke@435 314 verify_range(beg, end);
duke@435 315
duke@435 316 idx_t beg_full_word = word_index_round_up(beg);
duke@435 317 idx_t end_full_word = word_index(end);
duke@435 318
duke@435 319 assert(end_full_word - beg_full_word >= 32,
duke@435 320 "the range must include at least 32 bytes");
duke@435 321
duke@435 322 // The range includes at least one full word.
duke@435 323 par_put_range_within_word(beg, bit_index(beg_full_word), value);
duke@435 324 if (value) {
duke@435 325 set_large_range_of_words(beg_full_word, end_full_word);
duke@435 326 } else {
duke@435 327 clear_large_range_of_words(beg_full_word, end_full_word);
duke@435 328 }
duke@435 329 par_put_range_within_word(bit_index(end_full_word), end, value);
duke@435 330 }
duke@435 331
duke@435 332 bool BitMap::contains(const BitMap other) const {
duke@435 333 assert(size() == other.size(), "must have same size");
ysr@777 334 bm_word_t* dest_map = map();
ysr@777 335 bm_word_t* other_map = other.map();
duke@435 336 idx_t size = size_in_words();
duke@435 337 for (idx_t index = 0; index < size_in_words(); index++) {
ysr@777 338 bm_word_t word_union = dest_map[index] | other_map[index];
duke@435 339 // If this has more bits set than dest_map[index], then other is not a
duke@435 340 // subset.
duke@435 341 if (word_union != dest_map[index]) return false;
duke@435 342 }
duke@435 343 return true;
duke@435 344 }
duke@435 345
duke@435 346 bool BitMap::intersects(const BitMap other) const {
duke@435 347 assert(size() == other.size(), "must have same size");
ysr@777 348 bm_word_t* dest_map = map();
ysr@777 349 bm_word_t* other_map = other.map();
duke@435 350 idx_t size = size_in_words();
duke@435 351 for (idx_t index = 0; index < size_in_words(); index++) {
duke@435 352 if ((dest_map[index] & other_map[index]) != 0) return true;
duke@435 353 }
duke@435 354 // Otherwise, no intersection.
duke@435 355 return false;
duke@435 356 }
duke@435 357
duke@435 358 void BitMap::set_union(BitMap other) {
duke@435 359 assert(size() == other.size(), "must have same size");
ysr@777 360 bm_word_t* dest_map = map();
ysr@777 361 bm_word_t* other_map = other.map();
duke@435 362 idx_t size = size_in_words();
duke@435 363 for (idx_t index = 0; index < size_in_words(); index++) {
duke@435 364 dest_map[index] = dest_map[index] | other_map[index];
duke@435 365 }
duke@435 366 }
duke@435 367
duke@435 368
duke@435 369 void BitMap::set_difference(BitMap other) {
duke@435 370 assert(size() == other.size(), "must have same size");
ysr@777 371 bm_word_t* dest_map = map();
ysr@777 372 bm_word_t* other_map = other.map();
duke@435 373 idx_t size = size_in_words();
duke@435 374 for (idx_t index = 0; index < size_in_words(); index++) {
duke@435 375 dest_map[index] = dest_map[index] & ~(other_map[index]);
duke@435 376 }
duke@435 377 }
duke@435 378
duke@435 379
duke@435 380 void BitMap::set_intersection(BitMap other) {
duke@435 381 assert(size() == other.size(), "must have same size");
ysr@777 382 bm_word_t* dest_map = map();
ysr@777 383 bm_word_t* other_map = other.map();
duke@435 384 idx_t size = size_in_words();
duke@435 385 for (idx_t index = 0; index < size; index++) {
duke@435 386 dest_map[index] = dest_map[index] & other_map[index];
duke@435 387 }
duke@435 388 }
duke@435 389
duke@435 390
ysr@777 391 void BitMap::set_intersection_at_offset(BitMap other, idx_t offset) {
ysr@777 392 assert(other.size() >= offset, "offset not in range");
ysr@777 393 assert(other.size() - offset >= size(), "other not large enough");
ysr@777 394 // XXX Ideally, we would remove this restriction.
ysr@777 395 guarantee((offset % (sizeof(bm_word_t) * BitsPerByte)) == 0,
ysr@777 396 "Only handle aligned cases so far.");
ysr@777 397 bm_word_t* dest_map = map();
ysr@777 398 bm_word_t* other_map = other.map();
ysr@777 399 idx_t offset_word_ind = word_index(offset);
ysr@777 400 idx_t size = size_in_words();
ysr@777 401 for (idx_t index = 0; index < size; index++) {
ysr@777 402 dest_map[index] = dest_map[index] & other_map[offset_word_ind + index];
ysr@777 403 }
ysr@777 404 }
ysr@777 405
duke@435 406 bool BitMap::set_union_with_result(BitMap other) {
duke@435 407 assert(size() == other.size(), "must have same size");
duke@435 408 bool changed = false;
ysr@777 409 bm_word_t* dest_map = map();
ysr@777 410 bm_word_t* other_map = other.map();
duke@435 411 idx_t size = size_in_words();
duke@435 412 for (idx_t index = 0; index < size; index++) {
duke@435 413 idx_t temp = map(index) | other_map[index];
duke@435 414 changed = changed || (temp != map(index));
duke@435 415 map()[index] = temp;
duke@435 416 }
duke@435 417 return changed;
duke@435 418 }
duke@435 419
duke@435 420
duke@435 421 bool BitMap::set_difference_with_result(BitMap other) {
duke@435 422 assert(size() == other.size(), "must have same size");
duke@435 423 bool changed = false;
ysr@777 424 bm_word_t* dest_map = map();
ysr@777 425 bm_word_t* other_map = other.map();
duke@435 426 idx_t size = size_in_words();
duke@435 427 for (idx_t index = 0; index < size; index++) {
ysr@777 428 bm_word_t temp = dest_map[index] & ~(other_map[index]);
duke@435 429 changed = changed || (temp != dest_map[index]);
duke@435 430 dest_map[index] = temp;
duke@435 431 }
duke@435 432 return changed;
duke@435 433 }
duke@435 434
duke@435 435
duke@435 436 bool BitMap::set_intersection_with_result(BitMap other) {
duke@435 437 assert(size() == other.size(), "must have same size");
duke@435 438 bool changed = false;
ysr@777 439 bm_word_t* dest_map = map();
ysr@777 440 bm_word_t* other_map = other.map();
duke@435 441 idx_t size = size_in_words();
duke@435 442 for (idx_t index = 0; index < size; index++) {
ysr@777 443 bm_word_t orig = dest_map[index];
ysr@777 444 bm_word_t temp = orig & other_map[index];
duke@435 445 changed = changed || (temp != orig);
duke@435 446 dest_map[index] = temp;
duke@435 447 }
duke@435 448 return changed;
duke@435 449 }
duke@435 450
duke@435 451
duke@435 452 void BitMap::set_from(BitMap other) {
duke@435 453 assert(size() == other.size(), "must have same size");
ysr@777 454 bm_word_t* dest_map = map();
ysr@777 455 bm_word_t* other_map = other.map();
duke@435 456 idx_t size = size_in_words();
duke@435 457 for (idx_t index = 0; index < size; index++) {
duke@435 458 dest_map[index] = other_map[index];
duke@435 459 }
duke@435 460 }
duke@435 461
duke@435 462
duke@435 463 bool BitMap::is_same(BitMap other) {
duke@435 464 assert(size() == other.size(), "must have same size");
ysr@777 465 bm_word_t* dest_map = map();
ysr@777 466 bm_word_t* other_map = other.map();
duke@435 467 idx_t size = size_in_words();
duke@435 468 for (idx_t index = 0; index < size; index++) {
duke@435 469 if (dest_map[index] != other_map[index]) return false;
duke@435 470 }
duke@435 471 return true;
duke@435 472 }
duke@435 473
duke@435 474 bool BitMap::is_full() const {
ysr@777 475 bm_word_t* word = map();
duke@435 476 idx_t rest = size();
duke@435 477 for (; rest >= (idx_t) BitsPerWord; rest -= BitsPerWord) {
ysr@777 478 if (*word != (bm_word_t) AllBits) return false;
duke@435 479 word++;
duke@435 480 }
ysr@777 481 return rest == 0 || (*word | ~right_n_bits((int)rest)) == (bm_word_t) AllBits;
duke@435 482 }
duke@435 483
duke@435 484
duke@435 485 bool BitMap::is_empty() const {
ysr@777 486 bm_word_t* word = map();
duke@435 487 idx_t rest = size();
duke@435 488 for (; rest >= (idx_t) BitsPerWord; rest -= BitsPerWord) {
ysr@777 489 if (*word != (bm_word_t) NoBits) return false;
duke@435 490 word++;
duke@435 491 }
ysr@777 492 return rest == 0 || (*word & right_n_bits((int)rest)) == (bm_word_t) NoBits;
duke@435 493 }
duke@435 494
duke@435 495 void BitMap::clear_large() {
duke@435 496 clear_large_range_of_words(0, size_in_words());
duke@435 497 }
duke@435 498
duke@435 499 // Note that if the closure itself modifies the bitmap
duke@435 500 // then modifications in and to the left of the _bit_ being
duke@435 501 // currently sampled will not be seen. Note also that the
duke@435 502 // interval [leftOffset, rightOffset) is right open.
ysr@777 503 bool BitMap::iterate(BitMapClosure* blk, idx_t leftOffset, idx_t rightOffset) {
duke@435 504 verify_range(leftOffset, rightOffset);
duke@435 505
duke@435 506 idx_t startIndex = word_index(leftOffset);
duke@435 507 idx_t endIndex = MIN2(word_index(rightOffset) + 1, size_in_words());
duke@435 508 for (idx_t index = startIndex, offset = leftOffset;
duke@435 509 offset < rightOffset && index < endIndex;
duke@435 510 offset = (++index) << LogBitsPerWord) {
duke@435 511 idx_t rest = map(index) >> (offset & (BitsPerWord - 1));
ysr@777 512 for (; offset < rightOffset && rest != (bm_word_t)NoBits; offset++) {
duke@435 513 if (rest & 1) {
ysr@777 514 if (!blk->do_bit(offset)) return false;
duke@435 515 // resample at each closure application
duke@435 516 // (see, for instance, CMS bug 4525989)
duke@435 517 rest = map(index) >> (offset & (BitsPerWord -1));
duke@435 518 }
duke@435 519 rest = rest >> 1;
duke@435 520 }
duke@435 521 }
ysr@777 522 return true;
duke@435 523 }
duke@435 524
ysr@777 525 BitMap::idx_t* BitMap::_pop_count_table = NULL;
duke@435 526
ysr@777 527 void BitMap::init_pop_count_table() {
ysr@777 528 if (_pop_count_table == NULL) {
ysr@777 529 BitMap::idx_t *table = NEW_C_HEAP_ARRAY(idx_t, 256);
ysr@777 530 for (uint i = 0; i < 256; i++) {
ysr@777 531 table[i] = num_set_bits(i);
ysr@777 532 }
duke@435 533
ysr@777 534 intptr_t res = Atomic::cmpxchg_ptr((intptr_t) table,
ysr@777 535 (intptr_t*) &_pop_count_table,
ysr@777 536 (intptr_t) NULL_WORD);
ysr@777 537 if (res != NULL_WORD) {
ysr@777 538 guarantee( _pop_count_table == (void*) res, "invariant" );
ysr@777 539 FREE_C_HEAP_ARRAY(bm_word_t, table);
duke@435 540 }
duke@435 541 }
duke@435 542 }
duke@435 543
ysr@777 544 BitMap::idx_t BitMap::num_set_bits(bm_word_t w) {
ysr@777 545 idx_t bits = 0;
duke@435 546
ysr@777 547 while (w != 0) {
ysr@777 548 while ((w & 1) == 0) {
ysr@777 549 w >>= 1;
ysr@777 550 }
ysr@777 551 bits++;
ysr@777 552 w >>= 1;
duke@435 553 }
ysr@777 554 return bits;
ysr@777 555 }
duke@435 556
ysr@777 557 BitMap::idx_t BitMap::num_set_bits_from_table(unsigned char c) {
ysr@777 558 assert(_pop_count_table != NULL, "precondition");
ysr@777 559 return _pop_count_table[c];
ysr@777 560 }
duke@435 561
ysr@777 562 BitMap::idx_t BitMap::count_one_bits() const {
ysr@777 563 init_pop_count_table(); // If necessary.
ysr@777 564 idx_t sum = 0;
ysr@777 565 typedef unsigned char uchar;
ysr@777 566 for (idx_t i = 0; i < size_in_words(); i++) {
ysr@777 567 bm_word_t w = map()[i];
ysr@777 568 for (size_t j = 0; j < sizeof(bm_word_t); j++) {
ysr@777 569 sum += num_set_bits_from_table(uchar(w & 255));
ysr@777 570 w >>= 8;
duke@435 571 }
duke@435 572 }
ysr@777 573 return sum;
duke@435 574 }
duke@435 575
ysr@777 576
duke@435 577 #ifndef PRODUCT
duke@435 578
duke@435 579 void BitMap::print_on(outputStream* st) const {
duke@435 580 tty->print("Bitmap(%d):", size());
duke@435 581 for (idx_t index = 0; index < size(); index++) {
duke@435 582 tty->print("%c", at(index) ? '1' : '0');
duke@435 583 }
duke@435 584 tty->cr();
duke@435 585 }
duke@435 586
duke@435 587 #endif
duke@435 588
duke@435 589
ysr@777 590 BitMap2D::BitMap2D(bm_word_t* map, idx_t size_in_slots, idx_t bits_per_slot)
duke@435 591 : _bits_per_slot(bits_per_slot)
duke@435 592 , _map(map, size_in_slots * bits_per_slot)
duke@435 593 {
duke@435 594 }
duke@435 595
duke@435 596
duke@435 597 BitMap2D::BitMap2D(idx_t size_in_slots, idx_t bits_per_slot)
duke@435 598 : _bits_per_slot(bits_per_slot)
duke@435 599 , _map(size_in_slots * bits_per_slot)
duke@435 600 {
duke@435 601 }

mercurial