Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/utilities/bitMap.cpp
32285 views
/*1* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "memory/allocation.inline.hpp"26#include "utilities/bitMap.inline.hpp"27#include "utilities/copy.hpp"28#ifdef TARGET_OS_FAMILY_linux29# include "os_linux.inline.hpp"30#endif31#ifdef TARGET_OS_FAMILY_solaris32# include "os_solaris.inline.hpp"33#endif34#ifdef TARGET_OS_FAMILY_windows35# include "os_windows.inline.hpp"36#endif37#ifdef TARGET_OS_FAMILY_aix38# include "os_aix.inline.hpp"39#endif40#ifdef TARGET_OS_FAMILY_bsd41# include "os_bsd.inline.hpp"42#endif434445BitMap::BitMap(bm_word_t* map, idx_t size_in_bits) :46_map(map), _size(size_in_bits), _map_allocator(false)47{48assert(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption.");49assert(size_in_bits >= 0, "just checking");50}515253BitMap::BitMap(idx_t size_in_bits, bool in_resource_area) :54_map(NULL), _size(0), _map_allocator(false)55{56assert(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption.");57resize(size_in_bits, in_resource_area);58}5960void BitMap::resize(idx_t size_in_bits, bool in_resource_area) {61assert(size_in_bits >= 0, "just checking");62idx_t old_size_in_words = size_in_words();63bm_word_t* old_map = map();6465_size = size_in_bits;66idx_t new_size_in_words = size_in_words();67if (in_resource_area) {68_map = NEW_RESOURCE_ARRAY(bm_word_t, new_size_in_words);69} else {70if (old_map != NULL) {71_map_allocator.free();72}73_map = _map_allocator.allocate(new_size_in_words);74}75Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) _map,76MIN2(old_size_in_words, new_size_in_words));77if (new_size_in_words > old_size_in_words) {78clear_range_of_words(old_size_in_words, size_in_words());79}80}8182void BitMap::set_range_within_word(idx_t beg, idx_t end) {83// With a valid range (beg <= end), this test ensures that end != 0, as84// required by inverted_bit_mask_for_range. Also avoids an unnecessary write.85if (beg != end) {86bm_word_t mask = inverted_bit_mask_for_range(beg, end);87*word_addr(beg) |= ~mask;88}89}9091void BitMap::clear_range_within_word(idx_t beg, idx_t end) {92// With a valid range (beg <= end), this test ensures that end != 0, as93// required by inverted_bit_mask_for_range. Also avoids an unnecessary write.94if (beg != end) {95bm_word_t mask = inverted_bit_mask_for_range(beg, end);96*word_addr(beg) &= mask;97}98}99100void BitMap::par_put_range_within_word(idx_t beg, idx_t end, bool value) {101assert(value == 0 || value == 1, "0 for clear, 1 for set");102// With a valid range (beg <= end), this test ensures that end != 0, as103// required by inverted_bit_mask_for_range. Also avoids an unnecessary write.104if (beg != end) {105intptr_t* pw = (intptr_t*)word_addr(beg);106intptr_t w = *pw;107intptr_t mr = (intptr_t)inverted_bit_mask_for_range(beg, end);108intptr_t nw = value ? (w | ~mr) : (w & mr);109while (true) {110intptr_t res = Atomic::cmpxchg_ptr(nw, pw, w);111if (res == w) break;112w = res;113nw = value ? (w | ~mr) : (w & mr);114}115}116}117118void BitMap::set_range(idx_t beg, idx_t end) {119verify_range(beg, end);120121idx_t beg_full_word = word_index_round_up(beg);122idx_t end_full_word = word_index(end);123124if (beg_full_word < end_full_word) {125// The range includes at least one full word.126set_range_within_word(beg, bit_index(beg_full_word));127set_range_of_words(beg_full_word, end_full_word);128set_range_within_word(bit_index(end_full_word), end);129} else {130// The range spans at most 2 partial words.131idx_t boundary = MIN2(bit_index(beg_full_word), end);132set_range_within_word(beg, boundary);133set_range_within_word(boundary, end);134}135}136137void BitMap::clear_range(idx_t beg, idx_t end) {138verify_range(beg, end);139140idx_t beg_full_word = word_index_round_up(beg);141idx_t end_full_word = word_index(end);142143if (beg_full_word < end_full_word) {144// The range includes at least one full word.145clear_range_within_word(beg, bit_index(beg_full_word));146clear_range_of_words(beg_full_word, end_full_word);147clear_range_within_word(bit_index(end_full_word), end);148} else {149// The range spans at most 2 partial words.150idx_t boundary = MIN2(bit_index(beg_full_word), end);151clear_range_within_word(beg, boundary);152clear_range_within_word(boundary, end);153}154}155156bool BitMap::is_small_range_of_words(idx_t beg_full_word, idx_t end_full_word) {157// There is little point to call large version on small ranges.158// Need to check carefully, keeping potential idx_t underflow in mind.159// The threshold should be at least one word.160STATIC_ASSERT(small_range_words >= 1);161return (beg_full_word + small_range_words >= end_full_word);162}163164void BitMap::set_large_range(idx_t beg, idx_t end) {165verify_range(beg, end);166167idx_t beg_full_word = word_index_round_up(beg);168idx_t end_full_word = word_index(end);169170if (is_small_range_of_words(beg_full_word, end_full_word)) {171set_range(beg, end);172return;173}174175// The range includes at least one full word.176set_range_within_word(beg, bit_index(beg_full_word));177set_large_range_of_words(beg_full_word, end_full_word);178set_range_within_word(bit_index(end_full_word), end);179}180181void BitMap::clear_large_range(idx_t beg, idx_t end) {182verify_range(beg, end);183184idx_t beg_full_word = word_index_round_up(beg);185idx_t end_full_word = word_index(end);186187if (is_small_range_of_words(beg_full_word, end_full_word)) {188clear_range(beg, end);189return;190}191192// The range includes at least one full word.193clear_range_within_word(beg, bit_index(beg_full_word));194clear_large_range_of_words(beg_full_word, end_full_word);195clear_range_within_word(bit_index(end_full_word), end);196}197198void BitMap::at_put(idx_t offset, bool value) {199if (value) {200set_bit(offset);201} else {202clear_bit(offset);203}204}205206// Return true to indicate that this thread changed207// the bit, false to indicate that someone else did.208// In either case, the requested bit is in the209// requested state some time during the period that210// this thread is executing this call. More importantly,211// if no other thread is executing an action to212// change the requested bit to a state other than213// the one that this thread is trying to set it to,214// then the the bit is in the expected state215// at exit from this method. However, rather than216// make such a strong assertion here, based on217// assuming such constrained use (which though true218// today, could change in the future to service some219// funky parallel algorithm), we encourage callers220// to do such verification, as and when appropriate.221bool BitMap::par_at_put(idx_t bit, bool value) {222return value ? par_set_bit(bit) : par_clear_bit(bit);223}224225void BitMap::at_put_grow(idx_t offset, bool value) {226if (offset >= size()) {227resize(2 * MAX2(size(), offset));228}229at_put(offset, value);230}231232void BitMap::at_put_range(idx_t start_offset, idx_t end_offset, bool value) {233if (value) {234set_range(start_offset, end_offset);235} else {236clear_range(start_offset, end_offset);237}238}239240void BitMap::par_at_put_range(idx_t beg, idx_t end, bool value) {241verify_range(beg, end);242243idx_t beg_full_word = word_index_round_up(beg);244idx_t end_full_word = word_index(end);245246if (beg_full_word < end_full_word) {247// The range includes at least one full word.248par_put_range_within_word(beg, bit_index(beg_full_word), value);249if (value) {250set_range_of_words(beg_full_word, end_full_word);251} else {252clear_range_of_words(beg_full_word, end_full_word);253}254par_put_range_within_word(bit_index(end_full_word), end, value);255} else {256// The range spans at most 2 partial words.257idx_t boundary = MIN2(bit_index(beg_full_word), end);258par_put_range_within_word(beg, boundary, value);259par_put_range_within_word(boundary, end, value);260}261262}263264void BitMap::at_put_large_range(idx_t beg, idx_t end, bool value) {265if (value) {266set_large_range(beg, end);267} else {268clear_large_range(beg, end);269}270}271272void BitMap::par_at_put_large_range(idx_t beg, idx_t end, bool value) {273verify_range(beg, end);274275idx_t beg_full_word = word_index_round_up(beg);276idx_t end_full_word = word_index(end);277278if (is_small_range_of_words(beg_full_word, end_full_word)) {279par_at_put_range(beg, end, value);280return;281}282283// The range includes at least one full word.284par_put_range_within_word(beg, bit_index(beg_full_word), value);285if (value) {286set_large_range_of_words(beg_full_word, end_full_word);287} else {288clear_large_range_of_words(beg_full_word, end_full_word);289}290par_put_range_within_word(bit_index(end_full_word), end, value);291}292293bool BitMap::contains(const BitMap other) const {294assert(size() == other.size(), "must have same size");295bm_word_t* dest_map = map();296bm_word_t* other_map = other.map();297idx_t size = size_in_words();298for (idx_t index = 0; index < size_in_words(); index++) {299bm_word_t word_union = dest_map[index] | other_map[index];300// If this has more bits set than dest_map[index], then other is not a301// subset.302if (word_union != dest_map[index]) return false;303}304return true;305}306307bool BitMap::intersects(const BitMap other) const {308assert(size() == other.size(), "must have same size");309bm_word_t* dest_map = map();310bm_word_t* other_map = other.map();311idx_t size = size_in_words();312for (idx_t index = 0; index < size_in_words(); index++) {313if ((dest_map[index] & other_map[index]) != 0) return true;314}315// Otherwise, no intersection.316return false;317}318319void BitMap::set_union(BitMap other) {320assert(size() == other.size(), "must have same size");321bm_word_t* dest_map = map();322bm_word_t* other_map = other.map();323idx_t size = size_in_words();324for (idx_t index = 0; index < size_in_words(); index++) {325dest_map[index] = dest_map[index] | other_map[index];326}327}328329330void BitMap::set_difference(BitMap other) {331assert(size() == other.size(), "must have same size");332bm_word_t* dest_map = map();333bm_word_t* other_map = other.map();334idx_t size = size_in_words();335for (idx_t index = 0; index < size_in_words(); index++) {336dest_map[index] = dest_map[index] & ~(other_map[index]);337}338}339340341void BitMap::set_intersection(BitMap other) {342assert(size() == other.size(), "must have same size");343bm_word_t* dest_map = map();344bm_word_t* other_map = other.map();345idx_t size = size_in_words();346for (idx_t index = 0; index < size; index++) {347dest_map[index] = dest_map[index] & other_map[index];348}349}350351352void BitMap::set_intersection_at_offset(BitMap other, idx_t offset) {353assert(other.size() >= offset, "offset not in range");354assert(other.size() - offset >= size(), "other not large enough");355// XXX Ideally, we would remove this restriction.356guarantee((offset % (sizeof(bm_word_t) * BitsPerByte)) == 0,357"Only handle aligned cases so far.");358bm_word_t* dest_map = map();359bm_word_t* other_map = other.map();360idx_t offset_word_ind = word_index(offset);361idx_t size = size_in_words();362for (idx_t index = 0; index < size; index++) {363dest_map[index] = dest_map[index] & other_map[offset_word_ind + index];364}365}366367bool BitMap::set_union_with_result(BitMap other) {368assert(size() == other.size(), "must have same size");369bool changed = false;370bm_word_t* dest_map = map();371bm_word_t* other_map = other.map();372idx_t size = size_in_words();373for (idx_t index = 0; index < size; index++) {374idx_t temp = map(index) | other_map[index];375changed = changed || (temp != map(index));376map()[index] = temp;377}378return changed;379}380381382bool BitMap::set_difference_with_result(BitMap other) {383assert(size() == other.size(), "must have same size");384bool changed = false;385bm_word_t* dest_map = map();386bm_word_t* other_map = other.map();387idx_t size = size_in_words();388for (idx_t index = 0; index < size; index++) {389bm_word_t temp = dest_map[index] & ~(other_map[index]);390changed = changed || (temp != dest_map[index]);391dest_map[index] = temp;392}393return changed;394}395396397bool BitMap::set_intersection_with_result(BitMap other) {398assert(size() == other.size(), "must have same size");399bool changed = false;400bm_word_t* dest_map = map();401bm_word_t* other_map = other.map();402idx_t size = size_in_words();403for (idx_t index = 0; index < size; index++) {404bm_word_t orig = dest_map[index];405bm_word_t temp = orig & other_map[index];406changed = changed || (temp != orig);407dest_map[index] = temp;408}409return changed;410}411412413void BitMap::set_from(BitMap other) {414assert(size() == other.size(), "must have same size");415bm_word_t* dest_map = map();416bm_word_t* other_map = other.map();417idx_t size = size_in_words();418for (idx_t index = 0; index < size; index++) {419dest_map[index] = other_map[index];420}421}422423424bool BitMap::is_same(BitMap other) {425assert(size() == other.size(), "must have same size");426bm_word_t* dest_map = map();427bm_word_t* other_map = other.map();428idx_t size = size_in_words();429for (idx_t index = 0; index < size; index++) {430if (dest_map[index] != other_map[index]) return false;431}432return true;433}434435bool BitMap::is_full() const {436bm_word_t* word = map();437idx_t rest = size();438for (; rest >= (idx_t) BitsPerWord; rest -= BitsPerWord) {439if (*word != (bm_word_t) AllBits) return false;440word++;441}442return rest == 0 || (*word | ~right_n_bits((int)rest)) == (bm_word_t) AllBits;443}444445446bool BitMap::is_empty() const {447bm_word_t* word = map();448idx_t rest = size();449for (; rest >= (idx_t) BitsPerWord; rest -= BitsPerWord) {450if (*word != (bm_word_t) NoBits) return false;451word++;452}453return rest == 0 || (*word & right_n_bits((int)rest)) == (bm_word_t) NoBits;454}455456void BitMap::clear_large() {457clear_large_range_of_words(0, size_in_words());458}459460// Note that if the closure itself modifies the bitmap461// then modifications in and to the left of the _bit_ being462// currently sampled will not be seen. Note also that the463// interval [leftOffset, rightOffset) is right open.464bool BitMap::iterate(BitMapClosure* blk, idx_t leftOffset, idx_t rightOffset) {465verify_range(leftOffset, rightOffset);466467idx_t startIndex = word_index(leftOffset);468idx_t endIndex = MIN2(word_index(rightOffset) + 1, size_in_words());469for (idx_t index = startIndex, offset = leftOffset;470offset < rightOffset && index < endIndex;471offset = (++index) << LogBitsPerWord) {472idx_t rest = map(index) >> (offset & (BitsPerWord - 1));473for (; offset < rightOffset && rest != (bm_word_t)NoBits; offset++) {474if (rest & 1) {475if (!blk->do_bit(offset)) return false;476// resample at each closure application477// (see, for instance, CMS bug 4525989)478rest = map(index) >> (offset & (BitsPerWord -1));479}480rest = rest >> 1;481}482}483return true;484}485486BitMap::idx_t* BitMap::_pop_count_table = NULL;487488void BitMap::init_pop_count_table() {489if (_pop_count_table == NULL) {490BitMap::idx_t *table = NEW_C_HEAP_ARRAY(idx_t, 256, mtInternal);491for (uint i = 0; i < 256; i++) {492table[i] = num_set_bits(i);493}494495intptr_t res = Atomic::cmpxchg_ptr((intptr_t) table,496(intptr_t*) &_pop_count_table,497(intptr_t) NULL_WORD);498if (res != NULL_WORD) {499guarantee( _pop_count_table == (void*) res, "invariant" );500FREE_C_HEAP_ARRAY(bm_word_t, table, mtInternal);501}502}503}504505BitMap::idx_t BitMap::num_set_bits(bm_word_t w) {506idx_t bits = 0;507508while (w != 0) {509while ((w & 1) == 0) {510w >>= 1;511}512bits++;513w >>= 1;514}515return bits;516}517518BitMap::idx_t BitMap::num_set_bits_from_table(unsigned char c) {519assert(_pop_count_table != NULL, "precondition");520return _pop_count_table[c];521}522523BitMap::idx_t BitMap::count_one_bits() const {524init_pop_count_table(); // If necessary.525idx_t sum = 0;526typedef unsigned char uchar;527for (idx_t i = 0; i < size_in_words(); i++) {528bm_word_t w = map()[i];529for (size_t j = 0; j < sizeof(bm_word_t); j++) {530sum += num_set_bits_from_table(uchar(w & 255));531w >>= 8;532}533}534return sum;535}536537void BitMap::print_on_error(outputStream* st, const char* prefix) const {538st->print_cr("%s[" PTR_FORMAT ", " PTR_FORMAT ")",539prefix, p2i(map()), p2i((char*)map() + (size() >> LogBitsPerByte)));540}541542#ifndef PRODUCT543544void BitMap::print_on(outputStream* st) const {545tty->print("Bitmap(" SIZE_FORMAT "):", size());546for (idx_t index = 0; index < size(); index++) {547tty->print("%c", at(index) ? '1' : '0');548}549tty->cr();550}551552#endif553554555BitMap2D::BitMap2D(bm_word_t* map, idx_t size_in_slots, idx_t bits_per_slot)556: _bits_per_slot(bits_per_slot)557, _map(map, size_in_slots * bits_per_slot)558{559}560561562BitMap2D::BitMap2D(idx_t size_in_slots, idx_t bits_per_slot)563: _bits_per_slot(bits_per_slot)564, _map(size_in_slots * bits_per_slot)565{566}567568569