1 /*
2 * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "memory/allocation.inline.hpp"
27 #include "memory/resourceArea.hpp"
28 #include "runtime/atomic.hpp"
29 #include "utilities/bitMap.inline.hpp"
30 #include "utilities/copy.hpp"
31 #include "utilities/debug.hpp"
32 #include "utilities/population_count.hpp"
33
34 STATIC_ASSERT(sizeof(BitMap::bm_word_t) == BytesPerWord); // "Implementation assumption."
35
36 typedef BitMap::bm_word_t bm_word_t;
37 typedef BitMap::idx_t idx_t;
38
39 class ResourceBitMapAllocator : StackObj {
40 public:
allocate(idx_t size_in_words) const41 bm_word_t* allocate(idx_t size_in_words) const {
42 return NEW_RESOURCE_ARRAY(bm_word_t, size_in_words);
43 }
free(bm_word_t * map,idx_t size_in_words) const44 void free(bm_word_t* map, idx_t size_in_words) const {
45 // Don't free resource allocated arrays.
46 }
47 };
48
49 class CHeapBitMapAllocator : StackObj {
50 MEMFLAGS _flags;
51
52 public:
CHeapBitMapAllocator(MEMFLAGS flags)53 CHeapBitMapAllocator(MEMFLAGS flags) : _flags(flags) {}
allocate(size_t size_in_words) const54 bm_word_t* allocate(size_t size_in_words) const {
55 return ArrayAllocator<bm_word_t>::allocate(size_in_words, _flags);
56 }
free(bm_word_t * map,idx_t size_in_words) const57 void free(bm_word_t* map, idx_t size_in_words) const {
58 ArrayAllocator<bm_word_t>::free(map, size_in_words);
59 }
60 };
61
62 class ArenaBitMapAllocator : StackObj {
63 Arena* _arena;
64
65 public:
ArenaBitMapAllocator(Arena * arena)66 ArenaBitMapAllocator(Arena* arena) : _arena(arena) {}
allocate(idx_t size_in_words) const67 bm_word_t* allocate(idx_t size_in_words) const {
68 return (bm_word_t*)_arena->Amalloc(size_in_words * BytesPerWord);
69 }
free(bm_word_t * map,idx_t size_in_words) const70 void free(bm_word_t* map, idx_t size_in_words) const {
71 // ArenaBitMaps currently don't free memory.
72 }
73 };
74
75 template <class Allocator>
reallocate(const Allocator & allocator,bm_word_t * old_map,idx_t old_size_in_bits,idx_t new_size_in_bits,bool clear)76 BitMap::bm_word_t* BitMap::reallocate(const Allocator& allocator, bm_word_t* old_map, idx_t old_size_in_bits, idx_t new_size_in_bits, bool clear) {
77 size_t old_size_in_words = calc_size_in_words(old_size_in_bits);
78 size_t new_size_in_words = calc_size_in_words(new_size_in_bits);
79
80 bm_word_t* map = NULL;
81
82 if (new_size_in_words > 0) {
83 map = allocator.allocate(new_size_in_words);
84
85 if (old_map != NULL) {
86 Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) map,
87 MIN2(old_size_in_words, new_size_in_words));
88 }
89
90 if (clear && (new_size_in_bits > old_size_in_bits)) {
91 // If old_size_in_bits is not word-aligned, then the preceeding
92 // copy can include some trailing bits in the final copied word
93 // that also need to be cleared. See clear_range_within_word.
94 bm_word_t mask = bit_mask(old_size_in_bits) - 1;
95 map[raw_to_words_align_down(old_size_in_bits)] &= mask;
96 // Clear the remaining full words.
97 clear_range_of_words(map, old_size_in_words, new_size_in_words);
98 }
99 }
100
101 if (old_map != NULL) {
102 allocator.free(old_map, old_size_in_words);
103 }
104
105 return map;
106 }
107
108 template <class Allocator>
allocate(const Allocator & allocator,idx_t size_in_bits,bool clear)109 bm_word_t* BitMap::allocate(const Allocator& allocator, idx_t size_in_bits, bool clear) {
110 // Reuse reallocate to ensure that the new memory is cleared.
111 return reallocate(allocator, NULL, 0, size_in_bits, clear);
112 }
113
114 template <class Allocator>
free(const Allocator & allocator,bm_word_t * map,idx_t size_in_bits)115 void BitMap::free(const Allocator& allocator, bm_word_t* map, idx_t size_in_bits) {
116 bm_word_t* ret = reallocate(allocator, map, size_in_bits, 0);
117 assert(ret == NULL, "Reallocate shouldn't have allocated");
118 }
119
120 template <class Allocator>
resize(const Allocator & allocator,idx_t new_size_in_bits,bool clear)121 void BitMap::resize(const Allocator& allocator, idx_t new_size_in_bits, bool clear) {
122 bm_word_t* new_map = reallocate(allocator, map(), size(), new_size_in_bits, clear);
123
124 update(new_map, new_size_in_bits);
125 }
126
127 template <class Allocator>
initialize(const Allocator & allocator,idx_t size_in_bits,bool clear)128 void BitMap::initialize(const Allocator& allocator, idx_t size_in_bits, bool clear) {
129 assert(map() == NULL, "precondition");
130 assert(size() == 0, "precondition");
131
132 resize(allocator, size_in_bits, clear);
133 }
134
135 template <class Allocator>
reinitialize(const Allocator & allocator,idx_t new_size_in_bits,bool clear)136 void BitMap::reinitialize(const Allocator& allocator, idx_t new_size_in_bits, bool clear) {
137 // Remove previous bits - no need to clear
138 resize(allocator, 0, false /* clear */);
139
140 initialize(allocator, new_size_in_bits, clear);
141 }
142
ResourceBitMap(idx_t size_in_bits,bool clear)143 ResourceBitMap::ResourceBitMap(idx_t size_in_bits, bool clear)
144 : BitMap(allocate(ResourceBitMapAllocator(), size_in_bits, clear), size_in_bits) {
145 }
146
resize(idx_t new_size_in_bits)147 void ResourceBitMap::resize(idx_t new_size_in_bits) {
148 BitMap::resize(ResourceBitMapAllocator(), new_size_in_bits, true /* clear */);
149 }
150
initialize(idx_t size_in_bits)151 void ResourceBitMap::initialize(idx_t size_in_bits) {
152 BitMap::initialize(ResourceBitMapAllocator(), size_in_bits, true /* clear */);
153 }
154
reinitialize(idx_t size_in_bits)155 void ResourceBitMap::reinitialize(idx_t size_in_bits) {
156 BitMap::reinitialize(ResourceBitMapAllocator(), size_in_bits, true /* clear */);
157 }
158
ArenaBitMap(Arena * arena,idx_t size_in_bits)159 ArenaBitMap::ArenaBitMap(Arena* arena, idx_t size_in_bits)
160 : BitMap(allocate(ArenaBitMapAllocator(arena), size_in_bits), size_in_bits) {
161 }
162
CHeapBitMap(idx_t size_in_bits,MEMFLAGS flags,bool clear)163 CHeapBitMap::CHeapBitMap(idx_t size_in_bits, MEMFLAGS flags, bool clear)
164 : BitMap(allocate(CHeapBitMapAllocator(flags), size_in_bits, clear), size_in_bits), _flags(flags) {
165 }
166
~CHeapBitMap()167 CHeapBitMap::~CHeapBitMap() {
168 free(CHeapBitMapAllocator(_flags), map(), size());
169 }
170
resize(idx_t new_size_in_bits,bool clear)171 void CHeapBitMap::resize(idx_t new_size_in_bits, bool clear) {
172 BitMap::resize(CHeapBitMapAllocator(_flags), new_size_in_bits, clear);
173 }
174
initialize(idx_t size_in_bits,bool clear)175 void CHeapBitMap::initialize(idx_t size_in_bits, bool clear) {
176 BitMap::initialize(CHeapBitMapAllocator(_flags), size_in_bits, clear);
177 }
178
reinitialize(idx_t size_in_bits,bool clear)179 void CHeapBitMap::reinitialize(idx_t size_in_bits, bool clear) {
180 BitMap::reinitialize(CHeapBitMapAllocator(_flags), size_in_bits, clear);
181 }
182
183 #ifdef ASSERT
verify_size(idx_t size_in_bits)184 void BitMap::verify_size(idx_t size_in_bits) {
185 assert(size_in_bits <= max_size_in_bits(),
186 "out of bounds: " SIZE_FORMAT, size_in_bits);
187 }
188
verify_index(idx_t bit) const189 void BitMap::verify_index(idx_t bit) const {
190 assert(bit < _size,
191 "BitMap index out of bounds: " SIZE_FORMAT " >= " SIZE_FORMAT,
192 bit, _size);
193 }
194
verify_limit(idx_t bit) const195 void BitMap::verify_limit(idx_t bit) const {
196 assert(bit <= _size,
197 "BitMap limit out of bounds: " SIZE_FORMAT " > " SIZE_FORMAT,
198 bit, _size);
199 }
200
verify_range(idx_t beg,idx_t end) const201 void BitMap::verify_range(idx_t beg, idx_t end) const {
202 assert(beg <= end,
203 "BitMap range error: " SIZE_FORMAT " > " SIZE_FORMAT, beg, end);
204 verify_limit(end);
205 }
206 #endif // #ifdef ASSERT
207
pretouch()208 void BitMap::pretouch() {
209 os::pretouch_memory(word_addr(0), word_addr(size()));
210 }
211
set_range_within_word(idx_t beg,idx_t end)212 void BitMap::set_range_within_word(idx_t beg, idx_t end) {
213 // With a valid range (beg <= end), this test ensures that end != 0, as
214 // required by inverted_bit_mask_for_range. Also avoids an unnecessary write.
215 if (beg != end) {
216 bm_word_t mask = inverted_bit_mask_for_range(beg, end);
217 *word_addr(beg) |= ~mask;
218 }
219 }
220
clear_range_within_word(idx_t beg,idx_t end)221 void BitMap::clear_range_within_word(idx_t beg, idx_t end) {
222 // With a valid range (beg <= end), this test ensures that end != 0, as
223 // required by inverted_bit_mask_for_range. Also avoids an unnecessary write.
224 if (beg != end) {
225 bm_word_t mask = inverted_bit_mask_for_range(beg, end);
226 *word_addr(beg) &= mask;
227 }
228 }
229
par_put_range_within_word(idx_t beg,idx_t end,bool value)230 void BitMap::par_put_range_within_word(idx_t beg, idx_t end, bool value) {
231 assert(value == 0 || value == 1, "0 for clear, 1 for set");
232 // With a valid range (beg <= end), this test ensures that end != 0, as
233 // required by inverted_bit_mask_for_range. Also avoids an unnecessary write.
234 if (beg != end) {
235 bm_word_t* pw = word_addr(beg);
236 bm_word_t w = *pw;
237 bm_word_t mr = inverted_bit_mask_for_range(beg, end);
238 bm_word_t nw = value ? (w | ~mr) : (w & mr);
239 while (true) {
240 bm_word_t res = Atomic::cmpxchg(pw, w, nw);
241 if (res == w) break;
242 w = res;
243 nw = value ? (w | ~mr) : (w & mr);
244 }
245 }
246 }
247
set_range(idx_t beg,idx_t end)248 void BitMap::set_range(idx_t beg, idx_t end) {
249 verify_range(beg, end);
250
251 idx_t beg_full_word = to_words_align_up(beg);
252 idx_t end_full_word = to_words_align_down(end);
253
254 if (beg_full_word < end_full_word) {
255 // The range includes at least one full word.
256 set_range_within_word(beg, bit_index(beg_full_word));
257 set_range_of_words(beg_full_word, end_full_word);
258 set_range_within_word(bit_index(end_full_word), end);
259 } else {
260 // The range spans at most 2 partial words.
261 idx_t boundary = MIN2(bit_index(beg_full_word), end);
262 set_range_within_word(beg, boundary);
263 set_range_within_word(boundary, end);
264 }
265 }
266
clear_range(idx_t beg,idx_t end)267 void BitMap::clear_range(idx_t beg, idx_t end) {
268 verify_range(beg, end);
269
270 idx_t beg_full_word = to_words_align_up(beg);
271 idx_t end_full_word = to_words_align_down(end);
272
273 if (beg_full_word < end_full_word) {
274 // The range includes at least one full word.
275 clear_range_within_word(beg, bit_index(beg_full_word));
276 clear_range_of_words(beg_full_word, end_full_word);
277 clear_range_within_word(bit_index(end_full_word), end);
278 } else {
279 // The range spans at most 2 partial words.
280 idx_t boundary = MIN2(bit_index(beg_full_word), end);
281 clear_range_within_word(beg, boundary);
282 clear_range_within_word(boundary, end);
283 }
284 }
285
is_small_range_of_words(idx_t beg_full_word,idx_t end_full_word)286 bool BitMap::is_small_range_of_words(idx_t beg_full_word, idx_t end_full_word) {
287 // There is little point to call large version on small ranges.
288 // Need to check carefully, keeping potential idx_t over/underflow in mind,
289 // because beg_full_word > end_full_word can occur when beg and end are in
290 // the same word.
291 // The threshold should be at least one word.
292 STATIC_ASSERT(small_range_words >= 1);
293 return beg_full_word + small_range_words >= end_full_word;
294 }
295
set_large_range(idx_t beg,idx_t end)296 void BitMap::set_large_range(idx_t beg, idx_t end) {
297 verify_range(beg, end);
298
299 idx_t beg_full_word = to_words_align_up(beg);
300 idx_t end_full_word = to_words_align_down(end);
301
302 if (is_small_range_of_words(beg_full_word, end_full_word)) {
303 set_range(beg, end);
304 return;
305 }
306
307 // The range includes at least one full word.
308 set_range_within_word(beg, bit_index(beg_full_word));
309 set_large_range_of_words(beg_full_word, end_full_word);
310 set_range_within_word(bit_index(end_full_word), end);
311 }
312
clear_large_range(idx_t beg,idx_t end)313 void BitMap::clear_large_range(idx_t beg, idx_t end) {
314 verify_range(beg, end);
315
316 idx_t beg_full_word = to_words_align_up(beg);
317 idx_t end_full_word = to_words_align_down(end);
318
319 if (is_small_range_of_words(beg_full_word, end_full_word)) {
320 clear_range(beg, end);
321 return;
322 }
323
324 // The range includes at least one full word.
325 clear_range_within_word(beg, bit_index(beg_full_word));
326 clear_large_range_of_words(beg_full_word, end_full_word);
327 clear_range_within_word(bit_index(end_full_word), end);
328 }
329
at_put(idx_t offset,bool value)330 void BitMap::at_put(idx_t offset, bool value) {
331 if (value) {
332 set_bit(offset);
333 } else {
334 clear_bit(offset);
335 }
336 }
337
338 // Return true to indicate that this thread changed
339 // the bit, false to indicate that someone else did.
340 // In either case, the requested bit is in the
341 // requested state some time during the period that
342 // this thread is executing this call. More importantly,
343 // if no other thread is executing an action to
344 // change the requested bit to a state other than
345 // the one that this thread is trying to set it to,
346 // then the the bit is in the expected state
347 // at exit from this method. However, rather than
348 // make such a strong assertion here, based on
349 // assuming such constrained use (which though true
350 // today, could change in the future to service some
351 // funky parallel algorithm), we encourage callers
352 // to do such verification, as and when appropriate.
par_at_put(idx_t bit,bool value)353 bool BitMap::par_at_put(idx_t bit, bool value) {
354 return value ? par_set_bit(bit) : par_clear_bit(bit);
355 }
356
at_put_range(idx_t start_offset,idx_t end_offset,bool value)357 void BitMap::at_put_range(idx_t start_offset, idx_t end_offset, bool value) {
358 if (value) {
359 set_range(start_offset, end_offset);
360 } else {
361 clear_range(start_offset, end_offset);
362 }
363 }
364
par_at_put_range(idx_t beg,idx_t end,bool value)365 void BitMap::par_at_put_range(idx_t beg, idx_t end, bool value) {
366 verify_range(beg, end);
367
368 idx_t beg_full_word = to_words_align_up(beg);
369 idx_t end_full_word = to_words_align_down(end);
370
371 if (beg_full_word < end_full_word) {
372 // The range includes at least one full word.
373 par_put_range_within_word(beg, bit_index(beg_full_word), value);
374 if (value) {
375 set_range_of_words(beg_full_word, end_full_word);
376 } else {
377 clear_range_of_words(beg_full_word, end_full_word);
378 }
379 par_put_range_within_word(bit_index(end_full_word), end, value);
380 } else {
381 // The range spans at most 2 partial words.
382 idx_t boundary = MIN2(bit_index(beg_full_word), end);
383 par_put_range_within_word(beg, boundary, value);
384 par_put_range_within_word(boundary, end, value);
385 }
386
387 }
388
at_put_large_range(idx_t beg,idx_t end,bool value)389 void BitMap::at_put_large_range(idx_t beg, idx_t end, bool value) {
390 if (value) {
391 set_large_range(beg, end);
392 } else {
393 clear_large_range(beg, end);
394 }
395 }
396
par_at_put_large_range(idx_t beg,idx_t end,bool value)397 void BitMap::par_at_put_large_range(idx_t beg, idx_t end, bool value) {
398 verify_range(beg, end);
399
400 idx_t beg_full_word = to_words_align_up(beg);
401 idx_t end_full_word = to_words_align_down(end);
402
403 if (is_small_range_of_words(beg_full_word, end_full_word)) {
404 par_at_put_range(beg, end, value);
405 return;
406 }
407
408 // The range includes at least one full word.
409 par_put_range_within_word(beg, bit_index(beg_full_word), value);
410 if (value) {
411 set_large_range_of_words(beg_full_word, end_full_word);
412 } else {
413 clear_large_range_of_words(beg_full_word, end_full_word);
414 }
415 par_put_range_within_word(bit_index(end_full_word), end, value);
416 }
417
tail_mask(idx_t tail_bits)418 inline bm_word_t tail_mask(idx_t tail_bits) {
419 assert(tail_bits != 0, "precondition"); // Works, but shouldn't be called.
420 assert(tail_bits < (idx_t)BitsPerWord, "precondition");
421 return (bm_word_t(1) << tail_bits) - 1;
422 }
423
424 // Get the low tail_bits of value, which is the last partial word of a map.
tail_of_map(bm_word_t value,idx_t tail_bits)425 inline bm_word_t tail_of_map(bm_word_t value, idx_t tail_bits) {
426 return value & tail_mask(tail_bits);
427 }
428
429 // Compute the new last word of a map with a non-aligned length.
430 // new_value has the new trailing bits of the map in the low tail_bits.
431 // old_value is the last word of the map, including bits beyond the end.
432 // Returns old_value with the low tail_bits replaced by the corresponding
433 // bits in new_value.
merge_tail_of_map(bm_word_t new_value,bm_word_t old_value,idx_t tail_bits)434 inline bm_word_t merge_tail_of_map(bm_word_t new_value,
435 bm_word_t old_value,
436 idx_t tail_bits) {
437 bm_word_t mask = tail_mask(tail_bits);
438 return (new_value & mask) | (old_value & ~mask);
439 }
440
contains(const BitMap & other) const441 bool BitMap::contains(const BitMap& other) const {
442 assert(size() == other.size(), "must have same size");
443 const bm_word_t* dest_map = map();
444 const bm_word_t* other_map = other.map();
445 idx_t limit = to_words_align_down(size());
446 for (idx_t index = 0; index < limit; ++index) {
447 // false if other bitmap has bits set which are clear in this bitmap.
448 if ((~dest_map[index] & other_map[index]) != 0) return false;
449 }
450 idx_t rest = bit_in_word(size());
451 // true unless there is a partial-word tail in which the other
452 // bitmap has bits set which are clear in this bitmap.
453 return (rest == 0) || tail_of_map(~dest_map[limit] & other_map[limit], rest) == 0;
454 }
455
intersects(const BitMap & other) const456 bool BitMap::intersects(const BitMap& other) const {
457 assert(size() == other.size(), "must have same size");
458 const bm_word_t* dest_map = map();
459 const bm_word_t* other_map = other.map();
460 idx_t limit = to_words_align_down(size());
461 for (idx_t index = 0; index < limit; ++index) {
462 if ((dest_map[index] & other_map[index]) != 0) return true;
463 }
464 idx_t rest = bit_in_word(size());
465 // false unless there is a partial-word tail with non-empty intersection.
466 return (rest > 0) && tail_of_map(dest_map[limit] & other_map[limit], rest) != 0;
467 }
468
set_union(const BitMap & other)469 void BitMap::set_union(const BitMap& other) {
470 assert(size() == other.size(), "must have same size");
471 bm_word_t* dest_map = map();
472 const bm_word_t* other_map = other.map();
473 idx_t limit = to_words_align_down(size());
474 for (idx_t index = 0; index < limit; ++index) {
475 dest_map[index] |= other_map[index];
476 }
477 idx_t rest = bit_in_word(size());
478 if (rest > 0) {
479 bm_word_t orig = dest_map[limit];
480 dest_map[limit] = merge_tail_of_map(orig | other_map[limit], orig, rest);
481 }
482 }
483
set_difference(const BitMap & other)484 void BitMap::set_difference(const BitMap& other) {
485 assert(size() == other.size(), "must have same size");
486 bm_word_t* dest_map = map();
487 const bm_word_t* other_map = other.map();
488 idx_t limit = to_words_align_down(size());
489 for (idx_t index = 0; index < limit; ++index) {
490 dest_map[index] &= ~other_map[index];
491 }
492 idx_t rest = bit_in_word(size());
493 if (rest > 0) {
494 bm_word_t orig = dest_map[limit];
495 dest_map[limit] = merge_tail_of_map(orig & ~other_map[limit], orig, rest);
496 }
497 }
498
set_intersection(const BitMap & other)499 void BitMap::set_intersection(const BitMap& other) {
500 assert(size() == other.size(), "must have same size");
501 bm_word_t* dest_map = map();
502 const bm_word_t* other_map = other.map();
503 idx_t limit = to_words_align_down(size());
504 for (idx_t index = 0; index < limit; ++index) {
505 dest_map[index] &= other_map[index];
506 }
507 idx_t rest = bit_in_word(size());
508 if (rest > 0) {
509 bm_word_t orig = dest_map[limit];
510 dest_map[limit] = merge_tail_of_map(orig & other_map[limit], orig, rest);
511 }
512 }
513
set_union_with_result(const BitMap & other)514 bool BitMap::set_union_with_result(const BitMap& other) {
515 assert(size() == other.size(), "must have same size");
516 bool changed = false;
517 bm_word_t* dest_map = map();
518 const bm_word_t* other_map = other.map();
519 idx_t limit = to_words_align_down(size());
520 for (idx_t index = 0; index < limit; ++index) {
521 bm_word_t orig = dest_map[index];
522 bm_word_t temp = orig | other_map[index];
523 changed = changed || (temp != orig);
524 dest_map[index] = temp;
525 }
526 idx_t rest = bit_in_word(size());
527 if (rest > 0) {
528 bm_word_t orig = dest_map[limit];
529 bm_word_t temp = merge_tail_of_map(orig | other_map[limit], orig, rest);
530 changed = changed || (temp != orig);
531 dest_map[limit] = temp;
532 }
533 return changed;
534 }
535
set_difference_with_result(const BitMap & other)536 bool BitMap::set_difference_with_result(const BitMap& other) {
537 assert(size() == other.size(), "must have same size");
538 bool changed = false;
539 bm_word_t* dest_map = map();
540 const bm_word_t* other_map = other.map();
541 idx_t limit = to_words_align_down(size());
542 for (idx_t index = 0; index < limit; ++index) {
543 bm_word_t orig = dest_map[index];
544 bm_word_t temp = orig & ~other_map[index];
545 changed = changed || (temp != orig);
546 dest_map[index] = temp;
547 }
548 idx_t rest = bit_in_word(size());
549 if (rest > 0) {
550 bm_word_t orig = dest_map[limit];
551 bm_word_t temp = merge_tail_of_map(orig & ~other_map[limit], orig, rest);
552 changed = changed || (temp != orig);
553 dest_map[limit] = temp;
554 }
555 return changed;
556 }
557
set_intersection_with_result(const BitMap & other)558 bool BitMap::set_intersection_with_result(const BitMap& other) {
559 assert(size() == other.size(), "must have same size");
560 bool changed = false;
561 bm_word_t* dest_map = map();
562 const bm_word_t* other_map = other.map();
563 idx_t limit = to_words_align_down(size());
564 for (idx_t index = 0; index < limit; ++index) {
565 bm_word_t orig = dest_map[index];
566 bm_word_t temp = orig & other_map[index];
567 changed = changed || (temp != orig);
568 dest_map[index] = temp;
569 }
570 idx_t rest = bit_in_word(size());
571 if (rest > 0) {
572 bm_word_t orig = dest_map[limit];
573 bm_word_t temp = merge_tail_of_map(orig & other_map[limit], orig, rest);
574 changed = changed || (temp != orig);
575 dest_map[limit] = temp;
576 }
577 return changed;
578 }
579
set_from(const BitMap & other)580 void BitMap::set_from(const BitMap& other) {
581 assert(size() == other.size(), "must have same size");
582 bm_word_t* dest_map = map();
583 const bm_word_t* other_map = other.map();
584 idx_t copy_words = to_words_align_down(size());
585 Copy::disjoint_words((HeapWord*)other_map, (HeapWord*)dest_map, copy_words);
586 idx_t rest = bit_in_word(size());
587 if (rest > 0) {
588 dest_map[copy_words] = merge_tail_of_map(other_map[copy_words],
589 dest_map[copy_words],
590 rest);
591 }
592 }
593
is_same(const BitMap & other) const594 bool BitMap::is_same(const BitMap& other) const {
595 assert(size() == other.size(), "must have same size");
596 const bm_word_t* dest_map = map();
597 const bm_word_t* other_map = other.map();
598 idx_t limit = to_words_align_down(size());
599 for (idx_t index = 0; index < limit; ++index) {
600 if (dest_map[index] != other_map[index]) return false;
601 }
602 idx_t rest = bit_in_word(size());
603 return (rest == 0) || (tail_of_map(dest_map[limit] ^ other_map[limit], rest) == 0);
604 }
605
is_full() const606 bool BitMap::is_full() const {
607 const bm_word_t* words = map();
608 idx_t limit = to_words_align_down(size());
609 for (idx_t index = 0; index < limit; ++index) {
610 if (~words[index] != 0) return false;
611 }
612 idx_t rest = bit_in_word(size());
613 return (rest == 0) || (tail_of_map(~words[limit], rest) == 0);
614 }
615
is_empty() const616 bool BitMap::is_empty() const {
617 const bm_word_t* words = map();
618 idx_t limit = to_words_align_down(size());
619 for (idx_t index = 0; index < limit; ++index) {
620 if (words[index] != 0) return false;
621 }
622 idx_t rest = bit_in_word(size());
623 return (rest == 0) || (tail_of_map(words[limit], rest) == 0);
624 }
625
clear_large()626 void BitMap::clear_large() {
627 clear_large_range_of_words(0, size_in_words());
628 }
629
count_one_bits_in_range_of_words(idx_t beg_full_word,idx_t end_full_word) const630 BitMap::idx_t BitMap::count_one_bits_in_range_of_words(idx_t beg_full_word, idx_t end_full_word) const {
631 idx_t sum = 0;
632 for (idx_t i = beg_full_word; i < end_full_word; i++) {
633 bm_word_t w = map()[i];
634 sum += population_count(w);
635 }
636 return sum;
637 }
638
count_one_bits_within_word(idx_t beg,idx_t end) const639 BitMap::idx_t BitMap::count_one_bits_within_word(idx_t beg, idx_t end) const {
640 if (beg != end) {
641 assert(end > beg, "must be");
642 bm_word_t mask = ~inverted_bit_mask_for_range(beg, end);
643 bm_word_t w = *word_addr(beg);
644 w &= mask;
645 return population_count(w);
646 }
647 return 0;
648 }
649
count_one_bits() const650 BitMap::idx_t BitMap::count_one_bits() const {
651 return count_one_bits(0, size());
652 }
653
654 // Returns the number of bits set within [beg, end).
count_one_bits(idx_t beg,idx_t end) const655 BitMap::idx_t BitMap::count_one_bits(idx_t beg, idx_t end) const {
656 verify_range(beg, end);
657
658 idx_t beg_full_word = to_words_align_up(beg);
659 idx_t end_full_word = to_words_align_down(end);
660
661 idx_t sum = 0;
662
663 if (beg_full_word < end_full_word) {
664 // The range includes at least one full word.
665 sum += count_one_bits_within_word(beg, bit_index(beg_full_word));
666 sum += count_one_bits_in_range_of_words(beg_full_word, end_full_word);
667 sum += count_one_bits_within_word(bit_index(end_full_word), end);
668 } else {
669 // The range spans at most 2 partial words.
670 idx_t boundary = MIN2(bit_index(beg_full_word), end);
671 sum += count_one_bits_within_word(beg, boundary);
672 sum += count_one_bits_within_word(boundary, end);
673 }
674
675 assert(sum <= (beg - end), "must be");
676
677 return sum;
678
679 }
680
print_on_error(outputStream * st,const char * prefix) const681 void BitMap::print_on_error(outputStream* st, const char* prefix) const {
682 st->print_cr("%s[" PTR_FORMAT ", " PTR_FORMAT ")",
683 prefix, p2i(map()), p2i((char*)map() + (size() >> LogBitsPerByte)));
684 }
685
write_to(bm_word_t * buffer,size_t buffer_size_in_bytes) const686 void BitMap::write_to(bm_word_t* buffer, size_t buffer_size_in_bytes) const {
687 assert(buffer_size_in_bytes == size_in_bytes(), "must be");
688 memcpy(buffer, _map, size_in_bytes());
689 }
690
691 #ifndef PRODUCT
692
print_on(outputStream * st) const693 void BitMap::print_on(outputStream* st) const {
694 tty->print("Bitmap(" SIZE_FORMAT "):", size());
695 for (idx_t index = 0; index < size(); index++) {
696 tty->print("%c", at(index) ? '1' : '0');
697 }
698 tty->cr();
699 }
700
701 #endif
702