src/share/vm/utilities/bitMap.inline.hpp

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 2005-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
ysr@777 25
ysr@777 26 inline void BitMap::set_bit(idx_t bit) {
ysr@777 27 verify_index(bit);
ysr@777 28 *word_addr(bit) |= bit_mask(bit);
ysr@777 29 }
ysr@777 30
ysr@777 31 inline void BitMap::clear_bit(idx_t bit) {
ysr@777 32 verify_index(bit);
ysr@777 33 *word_addr(bit) &= ~bit_mask(bit);
ysr@777 34 }
ysr@777 35
duke@435 36 inline bool BitMap::par_set_bit(idx_t bit) {
duke@435 37 verify_index(bit);
duke@435 38 volatile idx_t* const addr = word_addr(bit);
duke@435 39 const idx_t mask = bit_mask(bit);
duke@435 40 idx_t old_val = *addr;
duke@435 41
duke@435 42 do {
duke@435 43 const idx_t new_val = old_val | mask;
duke@435 44 if (new_val == old_val) {
duke@435 45 return false; // Someone else beat us to it.
duke@435 46 }
duke@435 47 const idx_t cur_val = (idx_t) Atomic::cmpxchg_ptr((void*) new_val,
duke@435 48 (volatile void*) addr,
duke@435 49 (void*) old_val);
duke@435 50 if (cur_val == old_val) {
duke@435 51 return true; // Success.
duke@435 52 }
duke@435 53 old_val = cur_val; // The value changed, try again.
duke@435 54 } while (true);
duke@435 55 }
duke@435 56
duke@435 57 inline bool BitMap::par_clear_bit(idx_t bit) {
duke@435 58 verify_index(bit);
duke@435 59 volatile idx_t* const addr = word_addr(bit);
duke@435 60 const idx_t mask = ~bit_mask(bit);
duke@435 61 idx_t old_val = *addr;
duke@435 62
duke@435 63 do {
duke@435 64 const idx_t new_val = old_val & mask;
duke@435 65 if (new_val == old_val) {
duke@435 66 return false; // Someone else beat us to it.
duke@435 67 }
duke@435 68 const idx_t cur_val = (idx_t) Atomic::cmpxchg_ptr((void*) new_val,
duke@435 69 (volatile void*) addr,
duke@435 70 (void*) old_val);
duke@435 71 if (cur_val == old_val) {
duke@435 72 return true; // Success.
duke@435 73 }
duke@435 74 old_val = cur_val; // The value changed, try again.
duke@435 75 } while (true);
duke@435 76 }
duke@435 77
ysr@777 78 inline void BitMap::set_range(idx_t beg, idx_t end, RangeSizeHint hint) {
ysr@777 79 if (hint == small_range && end - beg == 1) {
ysr@777 80 set_bit(beg);
ysr@777 81 } else {
ysr@777 82 if (hint == large_range) {
ysr@777 83 set_large_range(beg, end);
ysr@777 84 } else {
ysr@777 85 set_range(beg, end);
ysr@777 86 }
ysr@777 87 }
ysr@777 88 }
ysr@777 89
ysr@777 90 inline void BitMap::clear_range(idx_t beg, idx_t end, RangeSizeHint hint) {
ysr@777 91 if (hint == small_range && end - beg == 1) {
ysr@777 92 clear_bit(beg);
ysr@777 93 } else {
ysr@777 94 if (hint == large_range) {
ysr@777 95 clear_large_range(beg, end);
ysr@777 96 } else {
ysr@777 97 clear_range(beg, end);
ysr@777 98 }
ysr@777 99 }
ysr@777 100 }
ysr@777 101
ysr@777 102 inline void BitMap::par_set_range(idx_t beg, idx_t end, RangeSizeHint hint) {
ysr@777 103 if (hint == small_range && end - beg == 1) {
ysr@777 104 par_at_put(beg, true);
ysr@777 105 } else {
ysr@777 106 if (hint == large_range) {
ysr@777 107 par_at_put_large_range(beg, end, true);
ysr@777 108 } else {
ysr@777 109 par_at_put_range(beg, end, true);
ysr@777 110 }
ysr@777 111 }
ysr@777 112 }
ysr@777 113
ysr@777 114 inline void BitMap::set_range_of_words(idx_t beg, idx_t end) {
ysr@777 115 bm_word_t* map = _map;
ysr@777 116 for (idx_t i = beg; i < end; ++i) map[i] = ~(uintptr_t)0;
ysr@777 117 }
ysr@777 118
ysr@777 119
ysr@777 120 inline void BitMap::clear_range_of_words(idx_t beg, idx_t end) {
ysr@777 121 bm_word_t* map = _map;
ysr@777 122 for (idx_t i = beg; i < end; ++i) map[i] = 0;
ysr@777 123 }
ysr@777 124
ysr@777 125
ysr@777 126 inline void BitMap::clear() {
ysr@777 127 clear_range_of_words(0, size_in_words());
ysr@777 128 }
ysr@777 129
ysr@777 130
ysr@777 131 inline void BitMap::par_clear_range(idx_t beg, idx_t end, RangeSizeHint hint) {
ysr@777 132 if (hint == small_range && end - beg == 1) {
ysr@777 133 par_at_put(beg, false);
ysr@777 134 } else {
ysr@777 135 if (hint == large_range) {
ysr@777 136 par_at_put_large_range(beg, end, false);
ysr@777 137 } else {
ysr@777 138 par_at_put_range(beg, end, false);
ysr@777 139 }
ysr@777 140 }
ysr@777 141 }
ysr@777 142
duke@435 143 inline BitMap::idx_t
ysr@777 144 BitMap::get_next_one_offset_inline(idx_t l_offset, idx_t r_offset) const {
ysr@777 145 assert(l_offset <= size(), "BitMap index out of bounds");
ysr@777 146 assert(r_offset <= size(), "BitMap index out of bounds");
ysr@777 147 assert(l_offset <= r_offset, "l_offset > r_offset ?");
duke@435 148
ysr@777 149 if (l_offset == r_offset) {
ysr@777 150 return l_offset;
duke@435 151 }
ysr@777 152 idx_t index = word_index(l_offset);
ysr@777 153 idx_t r_index = word_index(r_offset-1) + 1;
ysr@777 154 idx_t res_offset = l_offset;
duke@435 155
duke@435 156 // check bits including and to the _left_ of offset's position
ysr@777 157 idx_t pos = bit_in_word(res_offset);
ysr@777 158 idx_t res = map(index) >> pos;
ysr@777 159 if (res != (uintptr_t)NoBits) {
duke@435 160 // find the position of the 1-bit
ysr@777 161 for (; !(res & 1); res_offset++) {
duke@435 162 res = res >> 1;
duke@435 163 }
ysr@777 164 assert(res_offset >= l_offset &&
ysr@777 165 res_offset < r_offset, "just checking");
ysr@777 166 return MIN2(res_offset, r_offset);
duke@435 167 }
duke@435 168 // skip over all word length 0-bit runs
duke@435 169 for (index++; index < r_index; index++) {
duke@435 170 res = map(index);
ysr@777 171 if (res != (uintptr_t)NoBits) {
duke@435 172 // found a 1, return the offset
ysr@777 173 for (res_offset = bit_index(index); !(res & 1); res_offset++) {
duke@435 174 res = res >> 1;
duke@435 175 }
duke@435 176 assert(res & 1, "tautology; see loop condition");
ysr@777 177 assert(res_offset >= l_offset, "just checking");
ysr@777 178 return MIN2(res_offset, r_offset);
duke@435 179 }
duke@435 180 }
ysr@777 181 return r_offset;
duke@435 182 }
ysr@777 183
ysr@777 184 inline BitMap::idx_t
ysr@777 185 BitMap::get_next_zero_offset_inline(idx_t l_offset, idx_t r_offset) const {
ysr@777 186 assert(l_offset <= size(), "BitMap index out of bounds");
ysr@777 187 assert(r_offset <= size(), "BitMap index out of bounds");
ysr@777 188 assert(l_offset <= r_offset, "l_offset > r_offset ?");
ysr@777 189
ysr@777 190 if (l_offset == r_offset) {
ysr@777 191 return l_offset;
ysr@777 192 }
ysr@777 193 idx_t index = word_index(l_offset);
ysr@777 194 idx_t r_index = word_index(r_offset-1) + 1;
ysr@777 195 idx_t res_offset = l_offset;
ysr@777 196
ysr@777 197 // check bits including and to the _left_ of offset's position
ysr@777 198 idx_t pos = res_offset & (BitsPerWord - 1);
ysr@777 199 idx_t res = (map(index) >> pos) | left_n_bits((int)pos);
ysr@777 200
ysr@777 201 if (res != (uintptr_t)AllBits) {
ysr@777 202 // find the position of the 0-bit
ysr@777 203 for (; res & 1; res_offset++) {
ysr@777 204 res = res >> 1;
ysr@777 205 }
ysr@777 206 assert(res_offset >= l_offset, "just checking");
ysr@777 207 return MIN2(res_offset, r_offset);
ysr@777 208 }
ysr@777 209 // skip over all word length 1-bit runs
ysr@777 210 for (index++; index < r_index; index++) {
ysr@777 211 res = map(index);
ysr@777 212 if (res != (uintptr_t)AllBits) {
ysr@777 213 // found a 0, return the offset
ysr@777 214 for (res_offset = index << LogBitsPerWord; res & 1;
ysr@777 215 res_offset++) {
ysr@777 216 res = res >> 1;
ysr@777 217 }
ysr@777 218 assert(!(res & 1), "tautology; see loop condition");
ysr@777 219 assert(res_offset >= l_offset, "just checking");
ysr@777 220 return MIN2(res_offset, r_offset);
ysr@777 221 }
ysr@777 222 }
ysr@777 223 return r_offset;
ysr@777 224 }
ysr@777 225
ysr@777 226 inline BitMap::idx_t
ysr@777 227 BitMap::get_next_one_offset_inline_aligned_right(idx_t l_offset,
ysr@777 228 idx_t r_offset) const
ysr@777 229 {
ysr@777 230 verify_range(l_offset, r_offset);
ysr@777 231 assert(bit_in_word(r_offset) == 0, "r_offset not word-aligned");
ysr@777 232
ysr@777 233 if (l_offset == r_offset) {
ysr@777 234 return l_offset;
ysr@777 235 }
ysr@777 236 idx_t index = word_index(l_offset);
ysr@777 237 idx_t r_index = word_index(r_offset);
ysr@777 238 idx_t res_offset = l_offset;
ysr@777 239
ysr@777 240 // check bits including and to the _left_ of offset's position
ysr@777 241 idx_t res = map(index) >> bit_in_word(res_offset);
ysr@777 242 if (res != (uintptr_t)NoBits) {
ysr@777 243 // find the position of the 1-bit
ysr@777 244 for (; !(res & 1); res_offset++) {
ysr@777 245 res = res >> 1;
ysr@777 246 }
ysr@777 247 assert(res_offset >= l_offset &&
ysr@777 248 res_offset < r_offset, "just checking");
ysr@777 249 return res_offset;
ysr@777 250 }
ysr@777 251 // skip over all word length 0-bit runs
ysr@777 252 for (index++; index < r_index; index++) {
ysr@777 253 res = map(index);
ysr@777 254 if (res != (uintptr_t)NoBits) {
ysr@777 255 // found a 1, return the offset
ysr@777 256 for (res_offset = bit_index(index); !(res & 1); res_offset++) {
ysr@777 257 res = res >> 1;
ysr@777 258 }
ysr@777 259 assert(res & 1, "tautology; see loop condition");
ysr@777 260 assert(res_offset >= l_offset && res_offset < r_offset, "just checking");
ysr@777 261 return res_offset;
ysr@777 262 }
ysr@777 263 }
ysr@777 264 return r_offset;
ysr@777 265 }
ysr@777 266
ysr@777 267
ysr@777 268 // Returns a bit mask for a range of bits [beg, end) within a single word. Each
ysr@777 269 // bit in the mask is 0 if the bit is in the range, 1 if not in the range. The
ysr@777 270 // returned mask can be used directly to clear the range, or inverted to set the
ysr@777 271 // range. Note: end must not be 0.
ysr@777 272 inline BitMap::bm_word_t
ysr@777 273 BitMap::inverted_bit_mask_for_range(idx_t beg, idx_t end) const {
ysr@777 274 assert(end != 0, "does not work when end == 0");
ysr@777 275 assert(beg == end || word_index(beg) == word_index(end - 1),
ysr@777 276 "must be a single-word range");
ysr@777 277 bm_word_t mask = bit_mask(beg) - 1; // low (right) bits
ysr@777 278 if (bit_in_word(end) != 0) {
ysr@777 279 mask |= ~(bit_mask(end) - 1); // high (left) bits
ysr@777 280 }
ysr@777 281 return mask;
ysr@777 282 }
ysr@777 283
ysr@777 284 inline void BitMap::set_large_range_of_words(idx_t beg, idx_t end) {
ysr@777 285 memset(_map + beg, ~(unsigned char)0, (end - beg) * sizeof(uintptr_t));
ysr@777 286 }
ysr@777 287
ysr@777 288 inline void BitMap::clear_large_range_of_words(idx_t beg, idx_t end) {
ysr@777 289 memset(_map + beg, 0, (end - beg) * sizeof(uintptr_t));
ysr@777 290 }
ysr@777 291
ysr@777 292 inline BitMap::idx_t BitMap::word_index_round_up(idx_t bit) const {
ysr@777 293 idx_t bit_rounded_up = bit + (BitsPerWord - 1);
ysr@777 294 // Check for integer arithmetic overflow.
ysr@777 295 return bit_rounded_up > bit ? word_index(bit_rounded_up) : size_in_words();
ysr@777 296 }
ysr@777 297
ysr@777 298 inline BitMap::idx_t BitMap::get_next_one_offset(idx_t l_offset,
ysr@777 299 idx_t r_offset) const {
ysr@777 300 return get_next_one_offset_inline(l_offset, r_offset);
ysr@777 301 }
ysr@777 302
ysr@777 303 inline BitMap::idx_t BitMap::get_next_zero_offset(idx_t l_offset,
ysr@777 304 idx_t r_offset) const {
ysr@777 305 return get_next_zero_offset_inline(l_offset, r_offset);
ysr@777 306 }
ysr@777 307
ysr@777 308 inline void BitMap2D::clear() {
ysr@777 309 _map.clear();
ysr@777 310 }

mercurial