Tue, 05 May 2009 22:15:35 -0700
6833576: G1: assert illegal index, growableArray.hpp:186
Summary: The code that calculates the heap region index for an object address incorrectly used signed arithmetic.
Reviewed-by: jcoomes, ysr
ysr@777 | 1 | /* |
ysr@777 | 2 | * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. |
ysr@777 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
ysr@777 | 4 | * |
ysr@777 | 5 | * This code is free software; you can redistribute it and/or modify it |
ysr@777 | 6 | * under the terms of the GNU General Public License version 2 only, as |
ysr@777 | 7 | * published by the Free Software Foundation. |
ysr@777 | 8 | * |
ysr@777 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
ysr@777 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
ysr@777 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
ysr@777 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
ysr@777 | 13 | * accompanied this code). |
ysr@777 | 14 | * |
ysr@777 | 15 | * You should have received a copy of the GNU General Public License version |
ysr@777 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
ysr@777 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
ysr@777 | 18 | * |
ysr@777 | 19 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
ysr@777 | 20 | * CA 95054 USA or visit www.sun.com if you need additional information or |
ysr@777 | 21 | * have any questions. |
ysr@777 | 22 | * |
ysr@777 | 23 | */ |
ysr@777 | 24 | |
ysr@777 | 25 | #include "incls/_precompiled.incl" |
ysr@777 | 26 | #include "incls/_sparsePRT.cpp.incl" |
ysr@777 | 27 | |
ysr@777 | 28 | #define SPARSE_PRT_VERBOSE 0 |
ysr@777 | 29 | |
ysr@777 | 30 | #define UNROLL_CARD_LOOPS 1 |
ysr@777 | 31 | |
ysr@777 | 32 | void SparsePRT::init_iterator(SparsePRTIter* sprt_iter) { |
ysr@777 | 33 | sprt_iter->init(this); |
ysr@777 | 34 | } |
ysr@777 | 35 | |
ysr@777 | 36 | void SparsePRTEntry::init(short region_ind) { |
ysr@777 | 37 | _region_ind = region_ind; |
ysr@777 | 38 | _next_index = NullEntry; |
ysr@777 | 39 | #if UNROLL_CARD_LOOPS |
ysr@777 | 40 | assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll."); |
ysr@777 | 41 | _cards[0] = NullEntry; |
ysr@777 | 42 | _cards[1] = NullEntry; |
ysr@777 | 43 | _cards[2] = NullEntry; |
ysr@777 | 44 | _cards[3] = NullEntry; |
ysr@777 | 45 | #else |
ysr@777 | 46 | for (int i = 0; i < CardsPerEntry; i++) _cards[i] = NullEntry; |
ysr@777 | 47 | #endif |
ysr@777 | 48 | } |
ysr@777 | 49 | |
ysr@777 | 50 | bool SparsePRTEntry::contains_card(short card_index) const { |
ysr@777 | 51 | #if UNROLL_CARD_LOOPS |
ysr@777 | 52 | assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll."); |
ysr@777 | 53 | if (_cards[0] == card_index) return true; |
ysr@777 | 54 | if (_cards[1] == card_index) return true; |
ysr@777 | 55 | if (_cards[2] == card_index) return true; |
ysr@777 | 56 | if (_cards[3] == card_index) return true; |
ysr@777 | 57 | #else |
ysr@777 | 58 | for (int i = 0; i < CardsPerEntry; i++) { |
ysr@777 | 59 | if (_cards[i] == card_index) return true; |
ysr@777 | 60 | } |
ysr@777 | 61 | #endif |
ysr@777 | 62 | // Otherwise, we're full. |
ysr@777 | 63 | return false; |
ysr@777 | 64 | } |
ysr@777 | 65 | |
ysr@777 | 66 | int SparsePRTEntry::num_valid_cards() const { |
ysr@777 | 67 | int sum = 0; |
ysr@777 | 68 | #if UNROLL_CARD_LOOPS |
ysr@777 | 69 | assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll."); |
ysr@777 | 70 | if (_cards[0] != NullEntry) sum++; |
ysr@777 | 71 | if (_cards[1] != NullEntry) sum++; |
ysr@777 | 72 | if (_cards[2] != NullEntry) sum++; |
ysr@777 | 73 | if (_cards[3] != NullEntry) sum++; |
ysr@777 | 74 | #else |
ysr@777 | 75 | for (int i = 0; i < CardsPerEntry; i++) { |
ysr@777 | 76 | if (_cards[i] != NulLEntry) sum++; |
ysr@777 | 77 | } |
ysr@777 | 78 | #endif |
ysr@777 | 79 | // Otherwise, we're full. |
ysr@777 | 80 | return sum; |
ysr@777 | 81 | } |
ysr@777 | 82 | |
ysr@777 | 83 | SparsePRTEntry::AddCardResult SparsePRTEntry::add_card(short card_index) { |
ysr@777 | 84 | #if UNROLL_CARD_LOOPS |
ysr@777 | 85 | assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll."); |
ysr@777 | 86 | short c = _cards[0]; |
ysr@777 | 87 | if (c == card_index) return found; |
ysr@777 | 88 | if (c == NullEntry) { _cards[0] = card_index; return added; } |
ysr@777 | 89 | c = _cards[1]; |
ysr@777 | 90 | if (c == card_index) return found; |
ysr@777 | 91 | if (c == NullEntry) { _cards[1] = card_index; return added; } |
ysr@777 | 92 | c = _cards[2]; |
ysr@777 | 93 | if (c == card_index) return found; |
ysr@777 | 94 | if (c == NullEntry) { _cards[2] = card_index; return added; } |
ysr@777 | 95 | c = _cards[3]; |
ysr@777 | 96 | if (c == card_index) return found; |
ysr@777 | 97 | if (c == NullEntry) { _cards[3] = card_index; return added; } |
ysr@777 | 98 | #else |
ysr@777 | 99 | for (int i = 0; i < CardsPerEntry; i++) { |
ysr@777 | 100 | short c = _cards[i]; |
ysr@777 | 101 | if (c == card_index) return found; |
ysr@777 | 102 | if (c == NullEntry) { _cards[i] = card_index; return added; } |
ysr@777 | 103 | } |
ysr@777 | 104 | #endif |
ysr@777 | 105 | // Otherwise, we're full. |
ysr@777 | 106 | return overflow; |
ysr@777 | 107 | } |
ysr@777 | 108 | |
ysr@777 | 109 | void SparsePRTEntry::copy_cards(short* cards) const { |
ysr@777 | 110 | #if UNROLL_CARD_LOOPS |
ysr@777 | 111 | assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll."); |
ysr@777 | 112 | cards[0] = _cards[0]; |
ysr@777 | 113 | cards[1] = _cards[1]; |
ysr@777 | 114 | cards[2] = _cards[2]; |
ysr@777 | 115 | cards[3] = _cards[3]; |
ysr@777 | 116 | #else |
ysr@777 | 117 | for (int i = 0; i < CardsPerEntry; i++) { |
ysr@777 | 118 | cards[i] = _cards[i]; |
ysr@777 | 119 | } |
ysr@777 | 120 | #endif |
ysr@777 | 121 | } |
ysr@777 | 122 | |
ysr@777 | 123 | void SparsePRTEntry::copy_cards(SparsePRTEntry* e) const { |
ysr@777 | 124 | copy_cards(&e->_cards[0]); |
ysr@777 | 125 | } |
ysr@777 | 126 | |
ysr@777 | 127 | // ---------------------------------------------------------------------- |
ysr@777 | 128 | |
ysr@777 | 129 | RSHashTable::RSHashTable(size_t capacity) : |
ysr@777 | 130 | _capacity(capacity), _capacity_mask(capacity-1), |
ysr@777 | 131 | _occupied_entries(0), _occupied_cards(0), |
ysr@777 | 132 | _entries(NEW_C_HEAP_ARRAY(SparsePRTEntry, capacity)), |
ysr@777 | 133 | _buckets(NEW_C_HEAP_ARRAY(short, capacity)), |
ysr@777 | 134 | _next_deleted(NULL), _deleted(false), |
ysr@777 | 135 | _free_list(NullEntry), _free_region(0) |
ysr@777 | 136 | { |
ysr@777 | 137 | clear(); |
ysr@777 | 138 | } |
ysr@777 | 139 | |
ysr@777 | 140 | RSHashTable::~RSHashTable() { |
ysr@777 | 141 | if (_entries != NULL) { |
ysr@777 | 142 | FREE_C_HEAP_ARRAY(SparsePRTEntry, _entries); |
ysr@777 | 143 | _entries = NULL; |
ysr@777 | 144 | } |
ysr@777 | 145 | if (_buckets != NULL) { |
ysr@777 | 146 | FREE_C_HEAP_ARRAY(short, _buckets); |
ysr@777 | 147 | _buckets = NULL; |
ysr@777 | 148 | } |
ysr@777 | 149 | } |
ysr@777 | 150 | |
ysr@777 | 151 | void RSHashTable::clear() { |
ysr@777 | 152 | _occupied_entries = 0; |
ysr@777 | 153 | _occupied_cards = 0; |
ysr@777 | 154 | guarantee(_entries != NULL, "INV"); |
ysr@777 | 155 | guarantee(_buckets != NULL, "INV"); |
ysr@777 | 156 | // This will put -1 == NullEntry in the key field of all entries. |
ysr@777 | 157 | memset(_entries, -1, _capacity * sizeof(SparsePRTEntry)); |
ysr@777 | 158 | memset(_buckets, -1, _capacity * sizeof(short)); |
ysr@777 | 159 | _free_list = NullEntry; |
ysr@777 | 160 | _free_region = 0; |
ysr@777 | 161 | } |
ysr@777 | 162 | |
ysr@777 | 163 | bool RSHashTable::add_card(short region_ind, short card_index) { |
ysr@777 | 164 | SparsePRTEntry* e = entry_for_region_ind_create(region_ind); |
ysr@777 | 165 | assert(e != NULL && e->r_ind() == region_ind, |
ysr@777 | 166 | "Postcondition of call above."); |
ysr@777 | 167 | SparsePRTEntry::AddCardResult res = e->add_card(card_index); |
ysr@777 | 168 | if (res == SparsePRTEntry::added) _occupied_cards++; |
ysr@777 | 169 | #if SPARSE_PRT_VERBOSE |
ysr@777 | 170 | gclog_or_tty->print_cr(" after add_card[%d]: valid-cards = %d.", |
ysr@777 | 171 | pointer_delta(e, _entries, sizeof(SparsePRTEntry)), |
ysr@777 | 172 | e->num_valid_cards()); |
ysr@777 | 173 | #endif |
ysr@777 | 174 | assert(e->num_valid_cards() > 0, "Postcondition"); |
ysr@777 | 175 | return res != SparsePRTEntry::overflow; |
ysr@777 | 176 | } |
ysr@777 | 177 | |
ysr@777 | 178 | bool RSHashTable::get_cards(short region_ind, short* cards) { |
ysr@777 | 179 | short ind = (short) (region_ind & capacity_mask()); |
ysr@777 | 180 | short cur_ind = _buckets[ind]; |
ysr@777 | 181 | SparsePRTEntry* cur; |
ysr@777 | 182 | while (cur_ind != NullEntry && |
ysr@777 | 183 | (cur = entry(cur_ind))->r_ind() != region_ind) { |
ysr@777 | 184 | cur_ind = cur->next_index(); |
ysr@777 | 185 | } |
ysr@777 | 186 | |
ysr@777 | 187 | if (cur_ind == NullEntry) return false; |
ysr@777 | 188 | // Otherwise... |
ysr@777 | 189 | assert(cur->r_ind() == region_ind, "Postcondition of loop + test above."); |
ysr@777 | 190 | assert(cur->num_valid_cards() > 0, "Inv"); |
ysr@777 | 191 | cur->copy_cards(cards); |
ysr@777 | 192 | return true; |
ysr@777 | 193 | } |
ysr@777 | 194 | |
ysr@777 | 195 | bool RSHashTable::delete_entry(short region_ind) { |
ysr@777 | 196 | short ind = (short) (region_ind & capacity_mask()); |
ysr@777 | 197 | short* prev_loc = &_buckets[ind]; |
ysr@777 | 198 | short cur_ind = *prev_loc; |
ysr@777 | 199 | SparsePRTEntry* cur; |
ysr@777 | 200 | while (cur_ind != NullEntry && |
ysr@777 | 201 | (cur = entry(cur_ind))->r_ind() != region_ind) { |
ysr@777 | 202 | prev_loc = cur->next_index_addr(); |
ysr@777 | 203 | cur_ind = *prev_loc; |
ysr@777 | 204 | } |
ysr@777 | 205 | |
ysr@777 | 206 | if (cur_ind == NullEntry) return false; |
ysr@777 | 207 | // Otherwise, splice out "cur". |
ysr@777 | 208 | *prev_loc = cur->next_index(); |
ysr@777 | 209 | _occupied_cards -= cur->num_valid_cards(); |
ysr@777 | 210 | free_entry(cur_ind); |
ysr@777 | 211 | _occupied_entries--; |
ysr@777 | 212 | return true; |
ysr@777 | 213 | } |
ysr@777 | 214 | |
ysr@777 | 215 | SparsePRTEntry* RSHashTable::entry_for_region_ind(short region_ind) const { |
ysr@777 | 216 | assert(occupied_entries() < capacity(), "Precondition"); |
ysr@777 | 217 | short ind = (short) (region_ind & capacity_mask()); |
ysr@777 | 218 | short cur_ind = _buckets[ind]; |
ysr@777 | 219 | SparsePRTEntry* cur; |
ysr@777 | 220 | // XXX |
ysr@777 | 221 | // int k = 0; |
ysr@777 | 222 | while (cur_ind != NullEntry && |
ysr@777 | 223 | (cur = entry(cur_ind))->r_ind() != region_ind) { |
ysr@777 | 224 | /* |
ysr@777 | 225 | k++; |
ysr@777 | 226 | if (k > 10) { |
ysr@777 | 227 | gclog_or_tty->print_cr("RSHashTable::entry_for_region_ind(%d): " |
ysr@777 | 228 | "k = %d, cur_ind = %d.", region_ind, k, cur_ind); |
ysr@777 | 229 | if (k >= 1000) { |
ysr@777 | 230 | while (1) ; |
ysr@777 | 231 | } |
ysr@777 | 232 | } |
ysr@777 | 233 | */ |
ysr@777 | 234 | cur_ind = cur->next_index(); |
ysr@777 | 235 | } |
ysr@777 | 236 | |
ysr@777 | 237 | if (cur_ind != NullEntry) { |
ysr@777 | 238 | assert(cur->r_ind() == region_ind, "Loop postcondition + test"); |
ysr@777 | 239 | return cur; |
ysr@777 | 240 | } else { |
ysr@777 | 241 | return NULL; |
ysr@777 | 242 | } |
ysr@777 | 243 | } |
ysr@777 | 244 | |
ysr@777 | 245 | SparsePRTEntry* RSHashTable::entry_for_region_ind_create(short region_ind) { |
ysr@777 | 246 | SparsePRTEntry* res = entry_for_region_ind(region_ind); |
ysr@777 | 247 | if (res == NULL) { |
ysr@777 | 248 | short new_ind = alloc_entry(); |
ysr@777 | 249 | assert(0 <= new_ind && (size_t)new_ind < capacity(), "There should be room."); |
ysr@777 | 250 | res = entry(new_ind); |
ysr@777 | 251 | res->init(region_ind); |
ysr@777 | 252 | // Insert at front. |
ysr@777 | 253 | short ind = (short) (region_ind & capacity_mask()); |
ysr@777 | 254 | res->set_next_index(_buckets[ind]); |
ysr@777 | 255 | _buckets[ind] = new_ind; |
ysr@777 | 256 | _occupied_entries++; |
ysr@777 | 257 | } |
ysr@777 | 258 | return res; |
ysr@777 | 259 | } |
ysr@777 | 260 | |
ysr@777 | 261 | short RSHashTable::alloc_entry() { |
ysr@777 | 262 | short res; |
ysr@777 | 263 | if (_free_list != NullEntry) { |
ysr@777 | 264 | res = _free_list; |
ysr@777 | 265 | _free_list = entry(res)->next_index(); |
ysr@777 | 266 | return res; |
ysr@777 | 267 | } else if ((size_t) _free_region+1 < capacity()) { |
ysr@777 | 268 | res = _free_region; |
ysr@777 | 269 | _free_region++; |
ysr@777 | 270 | return res; |
ysr@777 | 271 | } else { |
ysr@777 | 272 | return NullEntry; |
ysr@777 | 273 | } |
ysr@777 | 274 | } |
ysr@777 | 275 | |
ysr@777 | 276 | |
ysr@777 | 277 | void RSHashTable::free_entry(short fi) { |
ysr@777 | 278 | entry(fi)->set_next_index(_free_list); |
ysr@777 | 279 | _free_list = fi; |
ysr@777 | 280 | } |
ysr@777 | 281 | |
ysr@777 | 282 | |
ysr@777 | 283 | void RSHashTable::add_entry(SparsePRTEntry* e) { |
ysr@777 | 284 | assert(e->num_valid_cards() > 0, "Precondition."); |
ysr@777 | 285 | SparsePRTEntry* e2 = entry_for_region_ind_create(e->r_ind()); |
ysr@777 | 286 | e->copy_cards(e2); |
ysr@777 | 287 | _occupied_cards += e2->num_valid_cards(); |
ysr@777 | 288 | assert(e2->num_valid_cards() > 0, "Postcondition."); |
ysr@777 | 289 | } |
ysr@777 | 290 | |
ysr@777 | 291 | RSHashTable* RSHashTable::_head_deleted_list = NULL; |
ysr@777 | 292 | |
ysr@777 | 293 | void RSHashTable::add_to_deleted_list(RSHashTable* rsht) { |
ysr@777 | 294 | assert(!rsht->deleted(), "Should delete only once."); |
ysr@777 | 295 | rsht->set_deleted(true); |
ysr@777 | 296 | RSHashTable* hd = _head_deleted_list; |
ysr@777 | 297 | while (true) { |
ysr@777 | 298 | rsht->_next_deleted = hd; |
ysr@777 | 299 | RSHashTable* res = |
ysr@777 | 300 | (RSHashTable*) |
ysr@777 | 301 | Atomic::cmpxchg_ptr(rsht, &_head_deleted_list, hd); |
ysr@777 | 302 | if (res == hd) return; |
ysr@777 | 303 | else hd = res; |
ysr@777 | 304 | } |
ysr@777 | 305 | } |
ysr@777 | 306 | |
ysr@777 | 307 | RSHashTable* RSHashTable::get_from_deleted_list() { |
ysr@777 | 308 | RSHashTable* hd = _head_deleted_list; |
ysr@777 | 309 | while (hd != NULL) { |
ysr@777 | 310 | RSHashTable* next = hd->next_deleted(); |
ysr@777 | 311 | RSHashTable* res = |
ysr@777 | 312 | (RSHashTable*) |
ysr@777 | 313 | Atomic::cmpxchg_ptr(next, &_head_deleted_list, hd); |
ysr@777 | 314 | if (res == hd) { |
ysr@777 | 315 | hd->set_next_deleted(NULL); |
ysr@777 | 316 | hd->set_deleted(false); |
ysr@777 | 317 | return hd; |
ysr@777 | 318 | } else { |
ysr@777 | 319 | hd = res; |
ysr@777 | 320 | } |
ysr@777 | 321 | } |
ysr@777 | 322 | return NULL; |
ysr@777 | 323 | } |
ysr@777 | 324 | |
ysr@777 | 325 | short /* RSHashTable:: */ RSHashTableIter::find_first_card_in_list() { |
ysr@777 | 326 | short res; |
ysr@777 | 327 | while (_bl_ind != RSHashTable::NullEntry) { |
ysr@777 | 328 | res = _rsht->entry(_bl_ind)->card(0); |
ysr@777 | 329 | if (res != SparsePRTEntry::NullEntry) { |
ysr@777 | 330 | return res; |
ysr@777 | 331 | } else { |
ysr@777 | 332 | _bl_ind = _rsht->entry(_bl_ind)->next_index(); |
ysr@777 | 333 | } |
ysr@777 | 334 | } |
ysr@777 | 335 | // Otherwise, none found: |
ysr@777 | 336 | return SparsePRTEntry::NullEntry; |
ysr@777 | 337 | } |
ysr@777 | 338 | |
ysr@777 | 339 | size_t /* RSHashTable:: */ RSHashTableIter::compute_card_ind(short ci) { |
ysr@777 | 340 | return |
ysr@777 | 341 | _heap_bot_card_ind |
ysr@777 | 342 | + (_rsht->entry(_bl_ind)->r_ind() * CardsPerRegion) |
ysr@777 | 343 | + ci; |
ysr@777 | 344 | } |
ysr@777 | 345 | |
ysr@777 | 346 | bool /* RSHashTable:: */ RSHashTableIter::has_next(size_t& card_index) { |
ysr@777 | 347 | _card_ind++; |
ysr@777 | 348 | short ci; |
ysr@777 | 349 | if (_card_ind < SparsePRTEntry::CardsPerEntry && |
ysr@777 | 350 | ((ci = _rsht->entry(_bl_ind)->card(_card_ind)) != |
ysr@777 | 351 | SparsePRTEntry::NullEntry)) { |
ysr@777 | 352 | card_index = compute_card_ind(ci); |
ysr@777 | 353 | return true; |
ysr@777 | 354 | } |
ysr@777 | 355 | // Otherwise, must find the next valid entry. |
ysr@777 | 356 | _card_ind = 0; |
ysr@777 | 357 | |
ysr@777 | 358 | if (_bl_ind != RSHashTable::NullEntry) { |
ysr@777 | 359 | _bl_ind = _rsht->entry(_bl_ind)->next_index(); |
ysr@777 | 360 | ci = find_first_card_in_list(); |
ysr@777 | 361 | if (ci != SparsePRTEntry::NullEntry) { |
ysr@777 | 362 | card_index = compute_card_ind(ci); |
ysr@777 | 363 | return true; |
ysr@777 | 364 | } |
ysr@777 | 365 | } |
ysr@777 | 366 | // If we didn't return above, must go to the next non-null table index. |
ysr@777 | 367 | _tbl_ind++; |
ysr@777 | 368 | while ((size_t)_tbl_ind < _rsht->capacity()) { |
ysr@777 | 369 | _bl_ind = _rsht->_buckets[_tbl_ind]; |
ysr@777 | 370 | ci = find_first_card_in_list(); |
ysr@777 | 371 | if (ci != SparsePRTEntry::NullEntry) { |
ysr@777 | 372 | card_index = compute_card_ind(ci); |
ysr@777 | 373 | return true; |
ysr@777 | 374 | } |
ysr@777 | 375 | // Otherwise, try next entry. |
ysr@777 | 376 | _tbl_ind++; |
ysr@777 | 377 | } |
ysr@777 | 378 | // Otherwise, there were no entry. |
ysr@777 | 379 | return false; |
ysr@777 | 380 | } |
ysr@777 | 381 | |
ysr@777 | 382 | bool RSHashTable::contains_card(short region_index, short card_index) const { |
ysr@777 | 383 | SparsePRTEntry* e = entry_for_region_ind(region_index); |
ysr@777 | 384 | return (e != NULL && e->contains_card(card_index)); |
ysr@777 | 385 | } |
ysr@777 | 386 | |
ysr@777 | 387 | size_t RSHashTable::mem_size() const { |
ysr@777 | 388 | return sizeof(this) + capacity() * (sizeof(SparsePRTEntry) + sizeof(short)); |
ysr@777 | 389 | } |
ysr@777 | 390 | |
ysr@777 | 391 | |
ysr@777 | 392 | // ---------------------------------------------------------------------- |
ysr@777 | 393 | |
ysr@777 | 394 | SparsePRT* SparsePRT::_head_expanded_list = NULL; |
ysr@777 | 395 | |
ysr@777 | 396 | void SparsePRT::add_to_expanded_list(SparsePRT* sprt) { |
ysr@777 | 397 | // We could expand multiple times in a pause -- only put on list once. |
ysr@777 | 398 | if (sprt->expanded()) return; |
ysr@777 | 399 | sprt->set_expanded(true); |
ysr@777 | 400 | SparsePRT* hd = _head_expanded_list; |
ysr@777 | 401 | while (true) { |
ysr@777 | 402 | sprt->_next_expanded = hd; |
ysr@777 | 403 | SparsePRT* res = |
ysr@777 | 404 | (SparsePRT*) |
ysr@777 | 405 | Atomic::cmpxchg_ptr(sprt, &_head_expanded_list, hd); |
ysr@777 | 406 | if (res == hd) return; |
ysr@777 | 407 | else hd = res; |
ysr@777 | 408 | } |
ysr@777 | 409 | } |
ysr@777 | 410 | |
ysr@777 | 411 | SparsePRT* SparsePRT::get_from_expanded_list() { |
ysr@777 | 412 | SparsePRT* hd = _head_expanded_list; |
ysr@777 | 413 | while (hd != NULL) { |
ysr@777 | 414 | SparsePRT* next = hd->next_expanded(); |
ysr@777 | 415 | SparsePRT* res = |
ysr@777 | 416 | (SparsePRT*) |
ysr@777 | 417 | Atomic::cmpxchg_ptr(next, &_head_expanded_list, hd); |
ysr@777 | 418 | if (res == hd) { |
ysr@777 | 419 | hd->set_next_expanded(NULL); |
ysr@777 | 420 | return hd; |
ysr@777 | 421 | } else { |
ysr@777 | 422 | hd = res; |
ysr@777 | 423 | } |
ysr@777 | 424 | } |
ysr@777 | 425 | return NULL; |
ysr@777 | 426 | } |
ysr@777 | 427 | |
ysr@777 | 428 | |
ysr@777 | 429 | void SparsePRT::cleanup_all() { |
ysr@777 | 430 | // First clean up all expanded tables so they agree on next and cur. |
ysr@777 | 431 | SparsePRT* sprt = get_from_expanded_list(); |
ysr@777 | 432 | while (sprt != NULL) { |
ysr@777 | 433 | sprt->cleanup(); |
ysr@777 | 434 | sprt = get_from_expanded_list(); |
ysr@777 | 435 | } |
ysr@777 | 436 | // Now delete all deleted RSHashTables. |
ysr@777 | 437 | RSHashTable* rsht = RSHashTable::get_from_deleted_list(); |
ysr@777 | 438 | while (rsht != NULL) { |
ysr@777 | 439 | #if SPARSE_PRT_VERBOSE |
ysr@777 | 440 | gclog_or_tty->print_cr("About to delete RSHT " PTR_FORMAT ".", rsht); |
ysr@777 | 441 | #endif |
ysr@777 | 442 | delete rsht; |
ysr@777 | 443 | rsht = RSHashTable::get_from_deleted_list(); |
ysr@777 | 444 | } |
ysr@777 | 445 | } |
ysr@777 | 446 | |
ysr@777 | 447 | |
ysr@777 | 448 | SparsePRT::SparsePRT(HeapRegion* hr) : |
ysr@777 | 449 | _expanded(false), _next_expanded(NULL) |
ysr@777 | 450 | { |
ysr@777 | 451 | _cur = new RSHashTable(InitialCapacity); |
ysr@777 | 452 | _next = _cur; |
ysr@777 | 453 | } |
ysr@777 | 454 | |
ysr@777 | 455 | SparsePRT::~SparsePRT() { |
ysr@777 | 456 | assert(_next != NULL && _cur != NULL, "Inv"); |
ysr@777 | 457 | if (_cur != _next) { delete _cur; } |
ysr@777 | 458 | delete _next; |
ysr@777 | 459 | } |
ysr@777 | 460 | |
ysr@777 | 461 | |
ysr@777 | 462 | size_t SparsePRT::mem_size() const { |
ysr@777 | 463 | // We ignore "_cur" here, because it either = _next, or else it is |
ysr@777 | 464 | // on the deleted list. |
ysr@777 | 465 | return sizeof(this) + _next->mem_size(); |
ysr@777 | 466 | } |
ysr@777 | 467 | |
ysr@777 | 468 | bool SparsePRT::add_card(short region_id, short card_index) { |
ysr@777 | 469 | #if SPARSE_PRT_VERBOSE |
ysr@777 | 470 | gclog_or_tty->print_cr(" Adding card %d from region %d to region %d sparse.", |
ysr@777 | 471 | card_index, region_id, _hr->hrs_index()); |
ysr@777 | 472 | #endif |
ysr@777 | 473 | if (_next->occupied_entries() * 2 > _next->capacity()) { |
ysr@777 | 474 | expand(); |
ysr@777 | 475 | } |
ysr@777 | 476 | return _next->add_card(region_id, card_index); |
ysr@777 | 477 | } |
ysr@777 | 478 | |
ysr@777 | 479 | bool SparsePRT::get_cards(short region_id, short* cards) { |
ysr@777 | 480 | return _next->get_cards(region_id, cards); |
ysr@777 | 481 | } |
ysr@777 | 482 | |
ysr@777 | 483 | bool SparsePRT::delete_entry(short region_id) { |
ysr@777 | 484 | return _next->delete_entry(region_id); |
ysr@777 | 485 | } |
ysr@777 | 486 | |
ysr@777 | 487 | void SparsePRT::clear() { |
ysr@777 | 488 | // If they differ, _next is bigger then cur, so next has no chance of |
ysr@777 | 489 | // being the initial size. |
ysr@777 | 490 | if (_next != _cur) { |
ysr@777 | 491 | delete _next; |
ysr@777 | 492 | } |
ysr@777 | 493 | |
ysr@777 | 494 | if (_cur->capacity() != InitialCapacity) { |
ysr@777 | 495 | delete _cur; |
ysr@777 | 496 | _cur = new RSHashTable(InitialCapacity); |
ysr@777 | 497 | } else { |
ysr@777 | 498 | _cur->clear(); |
ysr@777 | 499 | } |
ysr@777 | 500 | _next = _cur; |
ysr@777 | 501 | } |
ysr@777 | 502 | |
ysr@777 | 503 | void SparsePRT::cleanup() { |
ysr@777 | 504 | // Make sure that the current and next tables agree. (Another mechanism |
ysr@777 | 505 | // takes care of deleting now-unused tables.) |
ysr@777 | 506 | _cur = _next; |
tonyp@1052 | 507 | set_expanded(false); |
ysr@777 | 508 | } |
ysr@777 | 509 | |
ysr@777 | 510 | void SparsePRT::expand() { |
ysr@777 | 511 | RSHashTable* last = _next; |
ysr@777 | 512 | _next = new RSHashTable(last->capacity() * 2); |
ysr@777 | 513 | |
ysr@777 | 514 | #if SPARSE_PRT_VERBOSE |
ysr@777 | 515 | gclog_or_tty->print_cr(" Expanded sparse table for %d to %d.", |
ysr@777 | 516 | _hr->hrs_index(), _next->capacity()); |
ysr@777 | 517 | #endif |
ysr@777 | 518 | for (size_t i = 0; i < last->capacity(); i++) { |
ysr@777 | 519 | SparsePRTEntry* e = last->entry((int)i); |
ysr@777 | 520 | if (e->valid_entry()) { |
ysr@777 | 521 | #if SPARSE_PRT_VERBOSE |
ysr@777 | 522 | gclog_or_tty->print_cr(" During expansion, transferred entry for %d.", |
ysr@777 | 523 | e->r_ind()); |
ysr@777 | 524 | #endif |
ysr@777 | 525 | _next->add_entry(e); |
ysr@777 | 526 | } |
ysr@777 | 527 | } |
ysr@777 | 528 | if (last != _cur) |
ysr@777 | 529 | RSHashTable::add_to_deleted_list(last); |
ysr@777 | 530 | add_to_expanded_list(this); |
ysr@777 | 531 | } |