Thu, 15 Apr 2010 18:45:30 -0400
6939027: G1: assertion failure during the concurrent phase of cleanup
Summary: The outgoing region map is not maintained properly and it's causing an assert failure. Given that we don't actually use it, I'm removing it. I'm piggy-backing a small change on this which removes a message that it's printed before a Full GC when DisableExplicitGC is set.
Reviewed-by: apetrusenko, ysr
ysr@777 | 1 | /* |
xdono@1279 | 2 | * Copyright 2001-2009 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 | |
iveresov@1696 | 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 | |
johnc@1242 | 36 | void SparsePRTEntry::init(RegionIdx_t region_ind) { |
ysr@777 | 37 | _region_ind = region_ind; |
ysr@777 | 38 | _next_index = NullEntry; |
iveresov@1696 | 39 | |
ysr@777 | 40 | #if UNROLL_CARD_LOOPS |
iveresov@1696 | 41 | assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry"); |
iveresov@1696 | 42 | for (int i = 0; i < cards_num(); i += UnrollFactor) { |
iveresov@1696 | 43 | _cards[i] = NullEntry; |
iveresov@1696 | 44 | _cards[i + 1] = NullEntry; |
iveresov@1696 | 45 | _cards[i + 2] = NullEntry; |
iveresov@1696 | 46 | _cards[i + 3] = NullEntry; |
iveresov@1696 | 47 | } |
ysr@777 | 48 | #else |
iveresov@1696 | 49 | for (int i = 0; i < cards_num(); i++) |
johnc@1242 | 50 | _cards[i] = NullEntry; |
ysr@777 | 51 | #endif |
ysr@777 | 52 | } |
ysr@777 | 53 | |
johnc@1242 | 54 | bool SparsePRTEntry::contains_card(CardIdx_t card_index) const { |
ysr@777 | 55 | #if UNROLL_CARD_LOOPS |
iveresov@1696 | 56 | assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry"); |
iveresov@1696 | 57 | for (int i = 0; i < cards_num(); i += UnrollFactor) { |
iveresov@1696 | 58 | if (_cards[i] == card_index || |
iveresov@1696 | 59 | _cards[i + 1] == card_index || |
iveresov@1696 | 60 | _cards[i + 2] == card_index || |
iveresov@1696 | 61 | _cards[i + 3] == card_index) return true; |
iveresov@1696 | 62 | } |
ysr@777 | 63 | #else |
iveresov@1696 | 64 | for (int i = 0; i < cards_num(); i++) { |
ysr@777 | 65 | if (_cards[i] == card_index) return true; |
ysr@777 | 66 | } |
ysr@777 | 67 | #endif |
ysr@777 | 68 | // Otherwise, we're full. |
ysr@777 | 69 | return false; |
ysr@777 | 70 | } |
ysr@777 | 71 | |
ysr@777 | 72 | int SparsePRTEntry::num_valid_cards() const { |
ysr@777 | 73 | int sum = 0; |
ysr@777 | 74 | #if UNROLL_CARD_LOOPS |
iveresov@1696 | 75 | assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry"); |
iveresov@1696 | 76 | for (int i = 0; i < cards_num(); i += UnrollFactor) { |
iveresov@1696 | 77 | sum += (_cards[i] != NullEntry); |
iveresov@1696 | 78 | sum += (_cards[i + 1] != NullEntry); |
iveresov@1696 | 79 | sum += (_cards[i + 2] != NullEntry); |
iveresov@1696 | 80 | sum += (_cards[i + 3] != NullEntry); |
iveresov@1696 | 81 | } |
ysr@777 | 82 | #else |
iveresov@1696 | 83 | for (int i = 0; i < cards_num(); i++) { |
iveresov@1696 | 84 | sum += (_cards[i] != NullEntry); |
ysr@777 | 85 | } |
ysr@777 | 86 | #endif |
ysr@777 | 87 | // Otherwise, we're full. |
ysr@777 | 88 | return sum; |
ysr@777 | 89 | } |
ysr@777 | 90 | |
johnc@1242 | 91 | SparsePRTEntry::AddCardResult SparsePRTEntry::add_card(CardIdx_t card_index) { |
ysr@777 | 92 | #if UNROLL_CARD_LOOPS |
iveresov@1696 | 93 | assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry"); |
iveresov@1696 | 94 | CardIdx_t c; |
iveresov@1696 | 95 | for (int i = 0; i < cards_num(); i += UnrollFactor) { |
iveresov@1696 | 96 | c = _cards[i]; |
iveresov@1696 | 97 | if (c == card_index) return found; |
iveresov@1696 | 98 | if (c == NullEntry) { _cards[i] = card_index; return added; } |
iveresov@1696 | 99 | c = _cards[i + 1]; |
iveresov@1696 | 100 | if (c == card_index) return found; |
iveresov@1696 | 101 | if (c == NullEntry) { _cards[i + 1] = card_index; return added; } |
iveresov@1696 | 102 | c = _cards[i + 2]; |
iveresov@1696 | 103 | if (c == card_index) return found; |
iveresov@1696 | 104 | if (c == NullEntry) { _cards[i + 2] = card_index; return added; } |
iveresov@1696 | 105 | c = _cards[i + 3]; |
iveresov@1696 | 106 | if (c == card_index) return found; |
iveresov@1696 | 107 | if (c == NullEntry) { _cards[i + 3] = card_index; return added; } |
iveresov@1696 | 108 | } |
ysr@777 | 109 | #else |
iveresov@1696 | 110 | for (int i = 0; i < cards_num(); i++) { |
johnc@1242 | 111 | CardIdx_t c = _cards[i]; |
ysr@777 | 112 | if (c == card_index) return found; |
iveresov@1696 | 113 | if (c == NullEntry) { _cards[i] = card_index; return added; } |
ysr@777 | 114 | } |
ysr@777 | 115 | #endif |
ysr@777 | 116 | // Otherwise, we're full. |
ysr@777 | 117 | return overflow; |
ysr@777 | 118 | } |
ysr@777 | 119 | |
johnc@1242 | 120 | void SparsePRTEntry::copy_cards(CardIdx_t* cards) const { |
ysr@777 | 121 | #if UNROLL_CARD_LOOPS |
iveresov@1696 | 122 | assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry"); |
iveresov@1696 | 123 | for (int i = 0; i < cards_num(); i += UnrollFactor) { |
iveresov@1696 | 124 | cards[i] = _cards[i]; |
iveresov@1696 | 125 | cards[i + 1] = _cards[i + 1]; |
iveresov@1696 | 126 | cards[i + 2] = _cards[i + 2]; |
iveresov@1696 | 127 | cards[i + 3] = _cards[i + 3]; |
iveresov@1696 | 128 | } |
ysr@777 | 129 | #else |
iveresov@1696 | 130 | for (int i = 0; i < cards_num(); i++) { |
ysr@777 | 131 | cards[i] = _cards[i]; |
ysr@777 | 132 | } |
ysr@777 | 133 | #endif |
ysr@777 | 134 | } |
ysr@777 | 135 | |
ysr@777 | 136 | void SparsePRTEntry::copy_cards(SparsePRTEntry* e) const { |
ysr@777 | 137 | copy_cards(&e->_cards[0]); |
ysr@777 | 138 | } |
ysr@777 | 139 | |
ysr@777 | 140 | // ---------------------------------------------------------------------- |
ysr@777 | 141 | |
ysr@777 | 142 | RSHashTable::RSHashTable(size_t capacity) : |
ysr@777 | 143 | _capacity(capacity), _capacity_mask(capacity-1), |
ysr@777 | 144 | _occupied_entries(0), _occupied_cards(0), |
iveresov@1696 | 145 | _entries((SparsePRTEntry*)NEW_C_HEAP_ARRAY(char, SparsePRTEntry::size() * capacity)), |
johnc@1242 | 146 | _buckets(NEW_C_HEAP_ARRAY(int, capacity)), |
ysr@777 | 147 | _free_list(NullEntry), _free_region(0) |
ysr@777 | 148 | { |
ysr@777 | 149 | clear(); |
ysr@777 | 150 | } |
ysr@777 | 151 | |
ysr@777 | 152 | RSHashTable::~RSHashTable() { |
ysr@777 | 153 | if (_entries != NULL) { |
ysr@777 | 154 | FREE_C_HEAP_ARRAY(SparsePRTEntry, _entries); |
ysr@777 | 155 | _entries = NULL; |
ysr@777 | 156 | } |
ysr@777 | 157 | if (_buckets != NULL) { |
johnc@1242 | 158 | FREE_C_HEAP_ARRAY(int, _buckets); |
ysr@777 | 159 | _buckets = NULL; |
ysr@777 | 160 | } |
ysr@777 | 161 | } |
ysr@777 | 162 | |
ysr@777 | 163 | void RSHashTable::clear() { |
ysr@777 | 164 | _occupied_entries = 0; |
ysr@777 | 165 | _occupied_cards = 0; |
ysr@777 | 166 | guarantee(_entries != NULL, "INV"); |
ysr@777 | 167 | guarantee(_buckets != NULL, "INV"); |
johnc@1242 | 168 | |
johnc@1242 | 169 | guarantee(_capacity <= ((size_t)1 << (sizeof(int)*BitsPerByte-1)) - 1, |
johnc@1242 | 170 | "_capacity too large"); |
johnc@1242 | 171 | |
ysr@777 | 172 | // This will put -1 == NullEntry in the key field of all entries. |
iveresov@1696 | 173 | memset(_entries, NullEntry, _capacity * SparsePRTEntry::size()); |
iveresov@1696 | 174 | memset(_buckets, NullEntry, _capacity * sizeof(int)); |
ysr@777 | 175 | _free_list = NullEntry; |
ysr@777 | 176 | _free_region = 0; |
ysr@777 | 177 | } |
ysr@777 | 178 | |
johnc@1242 | 179 | bool RSHashTable::add_card(RegionIdx_t region_ind, CardIdx_t card_index) { |
ysr@777 | 180 | SparsePRTEntry* e = entry_for_region_ind_create(region_ind); |
ysr@777 | 181 | assert(e != NULL && e->r_ind() == region_ind, |
ysr@777 | 182 | "Postcondition of call above."); |
ysr@777 | 183 | SparsePRTEntry::AddCardResult res = e->add_card(card_index); |
ysr@777 | 184 | if (res == SparsePRTEntry::added) _occupied_cards++; |
ysr@777 | 185 | #if SPARSE_PRT_VERBOSE |
ysr@777 | 186 | gclog_or_tty->print_cr(" after add_card[%d]: valid-cards = %d.", |
iveresov@1696 | 187 | pointer_delta(e, _entries, SparsePRTEntry::size()), |
iveresov@1696 | 188 | e->num_valid_cards()); |
ysr@777 | 189 | #endif |
ysr@777 | 190 | assert(e->num_valid_cards() > 0, "Postcondition"); |
ysr@777 | 191 | return res != SparsePRTEntry::overflow; |
ysr@777 | 192 | } |
ysr@777 | 193 | |
johnc@1242 | 194 | bool RSHashTable::get_cards(RegionIdx_t region_ind, CardIdx_t* cards) { |
johnc@1242 | 195 | int ind = (int) (region_ind & capacity_mask()); |
johnc@1242 | 196 | int cur_ind = _buckets[ind]; |
ysr@777 | 197 | SparsePRTEntry* cur; |
ysr@777 | 198 | while (cur_ind != NullEntry && |
ysr@777 | 199 | (cur = entry(cur_ind))->r_ind() != region_ind) { |
ysr@777 | 200 | cur_ind = cur->next_index(); |
ysr@777 | 201 | } |
ysr@777 | 202 | |
ysr@777 | 203 | if (cur_ind == NullEntry) return false; |
ysr@777 | 204 | // Otherwise... |
ysr@777 | 205 | assert(cur->r_ind() == region_ind, "Postcondition of loop + test above."); |
ysr@777 | 206 | assert(cur->num_valid_cards() > 0, "Inv"); |
ysr@777 | 207 | cur->copy_cards(cards); |
ysr@777 | 208 | return true; |
ysr@777 | 209 | } |
ysr@777 | 210 | |
iveresov@1696 | 211 | SparsePRTEntry* RSHashTable::get_entry(RegionIdx_t region_ind) { |
iveresov@1696 | 212 | int ind = (int) (region_ind & capacity_mask()); |
iveresov@1696 | 213 | int cur_ind = _buckets[ind]; |
iveresov@1696 | 214 | SparsePRTEntry* cur; |
iveresov@1696 | 215 | while (cur_ind != NullEntry && |
iveresov@1696 | 216 | (cur = entry(cur_ind))->r_ind() != region_ind) { |
iveresov@1696 | 217 | cur_ind = cur->next_index(); |
iveresov@1696 | 218 | } |
iveresov@1696 | 219 | |
iveresov@1696 | 220 | if (cur_ind == NullEntry) return NULL; |
iveresov@1696 | 221 | // Otherwise... |
iveresov@1696 | 222 | assert(cur->r_ind() == region_ind, "Postcondition of loop + test above."); |
iveresov@1696 | 223 | assert(cur->num_valid_cards() > 0, "Inv"); |
iveresov@1696 | 224 | return cur; |
iveresov@1696 | 225 | } |
iveresov@1696 | 226 | |
johnc@1242 | 227 | bool RSHashTable::delete_entry(RegionIdx_t region_ind) { |
johnc@1242 | 228 | int ind = (int) (region_ind & capacity_mask()); |
johnc@1242 | 229 | int* prev_loc = &_buckets[ind]; |
johnc@1242 | 230 | int cur_ind = *prev_loc; |
ysr@777 | 231 | SparsePRTEntry* cur; |
ysr@777 | 232 | while (cur_ind != NullEntry && |
ysr@777 | 233 | (cur = entry(cur_ind))->r_ind() != region_ind) { |
ysr@777 | 234 | prev_loc = cur->next_index_addr(); |
ysr@777 | 235 | cur_ind = *prev_loc; |
ysr@777 | 236 | } |
ysr@777 | 237 | |
ysr@777 | 238 | if (cur_ind == NullEntry) return false; |
ysr@777 | 239 | // Otherwise, splice out "cur". |
ysr@777 | 240 | *prev_loc = cur->next_index(); |
ysr@777 | 241 | _occupied_cards -= cur->num_valid_cards(); |
ysr@777 | 242 | free_entry(cur_ind); |
ysr@777 | 243 | _occupied_entries--; |
ysr@777 | 244 | return true; |
ysr@777 | 245 | } |
ysr@777 | 246 | |
johnc@1242 | 247 | SparsePRTEntry* |
johnc@1242 | 248 | RSHashTable::entry_for_region_ind(RegionIdx_t region_ind) const { |
ysr@777 | 249 | assert(occupied_entries() < capacity(), "Precondition"); |
johnc@1242 | 250 | int ind = (int) (region_ind & capacity_mask()); |
johnc@1242 | 251 | int cur_ind = _buckets[ind]; |
ysr@777 | 252 | SparsePRTEntry* cur; |
ysr@777 | 253 | while (cur_ind != NullEntry && |
ysr@777 | 254 | (cur = entry(cur_ind))->r_ind() != region_ind) { |
ysr@777 | 255 | cur_ind = cur->next_index(); |
ysr@777 | 256 | } |
ysr@777 | 257 | |
ysr@777 | 258 | if (cur_ind != NullEntry) { |
ysr@777 | 259 | assert(cur->r_ind() == region_ind, "Loop postcondition + test"); |
ysr@777 | 260 | return cur; |
ysr@777 | 261 | } else { |
ysr@777 | 262 | return NULL; |
ysr@777 | 263 | } |
ysr@777 | 264 | } |
ysr@777 | 265 | |
johnc@1242 | 266 | SparsePRTEntry* |
johnc@1242 | 267 | RSHashTable::entry_for_region_ind_create(RegionIdx_t region_ind) { |
ysr@777 | 268 | SparsePRTEntry* res = entry_for_region_ind(region_ind); |
ysr@777 | 269 | if (res == NULL) { |
johnc@1242 | 270 | int new_ind = alloc_entry(); |
ysr@777 | 271 | assert(0 <= new_ind && (size_t)new_ind < capacity(), "There should be room."); |
ysr@777 | 272 | res = entry(new_ind); |
ysr@777 | 273 | res->init(region_ind); |
ysr@777 | 274 | // Insert at front. |
johnc@1242 | 275 | int ind = (int) (region_ind & capacity_mask()); |
ysr@777 | 276 | res->set_next_index(_buckets[ind]); |
ysr@777 | 277 | _buckets[ind] = new_ind; |
ysr@777 | 278 | _occupied_entries++; |
ysr@777 | 279 | } |
ysr@777 | 280 | return res; |
ysr@777 | 281 | } |
ysr@777 | 282 | |
johnc@1242 | 283 | int RSHashTable::alloc_entry() { |
johnc@1242 | 284 | int res; |
ysr@777 | 285 | if (_free_list != NullEntry) { |
ysr@777 | 286 | res = _free_list; |
ysr@777 | 287 | _free_list = entry(res)->next_index(); |
ysr@777 | 288 | return res; |
ysr@777 | 289 | } else if ((size_t) _free_region+1 < capacity()) { |
ysr@777 | 290 | res = _free_region; |
ysr@777 | 291 | _free_region++; |
ysr@777 | 292 | return res; |
ysr@777 | 293 | } else { |
ysr@777 | 294 | return NullEntry; |
ysr@777 | 295 | } |
ysr@777 | 296 | } |
ysr@777 | 297 | |
johnc@1242 | 298 | void RSHashTable::free_entry(int fi) { |
ysr@777 | 299 | entry(fi)->set_next_index(_free_list); |
ysr@777 | 300 | _free_list = fi; |
ysr@777 | 301 | } |
ysr@777 | 302 | |
ysr@777 | 303 | void RSHashTable::add_entry(SparsePRTEntry* e) { |
ysr@777 | 304 | assert(e->num_valid_cards() > 0, "Precondition."); |
ysr@777 | 305 | SparsePRTEntry* e2 = entry_for_region_ind_create(e->r_ind()); |
ysr@777 | 306 | e->copy_cards(e2); |
ysr@777 | 307 | _occupied_cards += e2->num_valid_cards(); |
ysr@777 | 308 | assert(e2->num_valid_cards() > 0, "Postcondition."); |
ysr@777 | 309 | } |
ysr@777 | 310 | |
johnc@1242 | 311 | CardIdx_t /* RSHashTable:: */ RSHashTableIter::find_first_card_in_list() { |
johnc@1242 | 312 | CardIdx_t res; |
ysr@777 | 313 | while (_bl_ind != RSHashTable::NullEntry) { |
ysr@777 | 314 | res = _rsht->entry(_bl_ind)->card(0); |
ysr@777 | 315 | if (res != SparsePRTEntry::NullEntry) { |
ysr@777 | 316 | return res; |
ysr@777 | 317 | } else { |
ysr@777 | 318 | _bl_ind = _rsht->entry(_bl_ind)->next_index(); |
ysr@777 | 319 | } |
ysr@777 | 320 | } |
ysr@777 | 321 | // Otherwise, none found: |
ysr@777 | 322 | return SparsePRTEntry::NullEntry; |
ysr@777 | 323 | } |
ysr@777 | 324 | |
johnc@1242 | 325 | size_t /* RSHashTable:: */ RSHashTableIter::compute_card_ind(CardIdx_t ci) { |
ysr@777 | 326 | return |
ysr@777 | 327 | _heap_bot_card_ind |
tonyp@1377 | 328 | + (_rsht->entry(_bl_ind)->r_ind() * HeapRegion::CardsPerRegion) |
ysr@777 | 329 | + ci; |
ysr@777 | 330 | } |
ysr@777 | 331 | |
ysr@777 | 332 | bool /* RSHashTable:: */ RSHashTableIter::has_next(size_t& card_index) { |
ysr@777 | 333 | _card_ind++; |
johnc@1242 | 334 | CardIdx_t ci; |
iveresov@1696 | 335 | if (_card_ind < SparsePRTEntry::cards_num() && |
ysr@777 | 336 | ((ci = _rsht->entry(_bl_ind)->card(_card_ind)) != |
ysr@777 | 337 | SparsePRTEntry::NullEntry)) { |
ysr@777 | 338 | card_index = compute_card_ind(ci); |
ysr@777 | 339 | return true; |
ysr@777 | 340 | } |
ysr@777 | 341 | // Otherwise, must find the next valid entry. |
ysr@777 | 342 | _card_ind = 0; |
ysr@777 | 343 | |
ysr@777 | 344 | if (_bl_ind != RSHashTable::NullEntry) { |
ysr@777 | 345 | _bl_ind = _rsht->entry(_bl_ind)->next_index(); |
ysr@777 | 346 | ci = find_first_card_in_list(); |
ysr@777 | 347 | if (ci != SparsePRTEntry::NullEntry) { |
ysr@777 | 348 | card_index = compute_card_ind(ci); |
ysr@777 | 349 | return true; |
ysr@777 | 350 | } |
ysr@777 | 351 | } |
ysr@777 | 352 | // If we didn't return above, must go to the next non-null table index. |
ysr@777 | 353 | _tbl_ind++; |
ysr@777 | 354 | while ((size_t)_tbl_ind < _rsht->capacity()) { |
ysr@777 | 355 | _bl_ind = _rsht->_buckets[_tbl_ind]; |
ysr@777 | 356 | ci = find_first_card_in_list(); |
ysr@777 | 357 | if (ci != SparsePRTEntry::NullEntry) { |
ysr@777 | 358 | card_index = compute_card_ind(ci); |
ysr@777 | 359 | return true; |
ysr@777 | 360 | } |
ysr@777 | 361 | // Otherwise, try next entry. |
ysr@777 | 362 | _tbl_ind++; |
ysr@777 | 363 | } |
ysr@777 | 364 | // Otherwise, there were no entry. |
ysr@777 | 365 | return false; |
ysr@777 | 366 | } |
ysr@777 | 367 | |
johnc@1242 | 368 | bool RSHashTable::contains_card(RegionIdx_t region_index, CardIdx_t card_index) const { |
ysr@777 | 369 | SparsePRTEntry* e = entry_for_region_ind(region_index); |
ysr@777 | 370 | return (e != NULL && e->contains_card(card_index)); |
ysr@777 | 371 | } |
ysr@777 | 372 | |
ysr@777 | 373 | size_t RSHashTable::mem_size() const { |
johnc@1242 | 374 | return sizeof(this) + |
iveresov@1696 | 375 | capacity() * (SparsePRTEntry::size() + sizeof(int)); |
ysr@777 | 376 | } |
ysr@777 | 377 | |
ysr@777 | 378 | // ---------------------------------------------------------------------- |
ysr@777 | 379 | |
ysr@777 | 380 | SparsePRT* SparsePRT::_head_expanded_list = NULL; |
ysr@777 | 381 | |
ysr@777 | 382 | void SparsePRT::add_to_expanded_list(SparsePRT* sprt) { |
ysr@777 | 383 | // We could expand multiple times in a pause -- only put on list once. |
ysr@777 | 384 | if (sprt->expanded()) return; |
ysr@777 | 385 | sprt->set_expanded(true); |
ysr@777 | 386 | SparsePRT* hd = _head_expanded_list; |
ysr@777 | 387 | while (true) { |
ysr@777 | 388 | sprt->_next_expanded = hd; |
ysr@777 | 389 | SparsePRT* res = |
ysr@777 | 390 | (SparsePRT*) |
ysr@777 | 391 | Atomic::cmpxchg_ptr(sprt, &_head_expanded_list, hd); |
ysr@777 | 392 | if (res == hd) return; |
ysr@777 | 393 | else hd = res; |
ysr@777 | 394 | } |
ysr@777 | 395 | } |
ysr@777 | 396 | |
johnc@1242 | 397 | |
ysr@777 | 398 | SparsePRT* SparsePRT::get_from_expanded_list() { |
ysr@777 | 399 | SparsePRT* hd = _head_expanded_list; |
ysr@777 | 400 | while (hd != NULL) { |
ysr@777 | 401 | SparsePRT* next = hd->next_expanded(); |
ysr@777 | 402 | SparsePRT* res = |
ysr@777 | 403 | (SparsePRT*) |
ysr@777 | 404 | Atomic::cmpxchg_ptr(next, &_head_expanded_list, hd); |
ysr@777 | 405 | if (res == hd) { |
ysr@777 | 406 | hd->set_next_expanded(NULL); |
ysr@777 | 407 | return hd; |
ysr@777 | 408 | } else { |
ysr@777 | 409 | hd = res; |
ysr@777 | 410 | } |
ysr@777 | 411 | } |
ysr@777 | 412 | return NULL; |
ysr@777 | 413 | } |
ysr@777 | 414 | |
ysr@777 | 415 | |
ysr@777 | 416 | void SparsePRT::cleanup_all() { |
ysr@777 | 417 | // First clean up all expanded tables so they agree on next and cur. |
ysr@777 | 418 | SparsePRT* sprt = get_from_expanded_list(); |
ysr@777 | 419 | while (sprt != NULL) { |
ysr@777 | 420 | sprt->cleanup(); |
ysr@777 | 421 | sprt = get_from_expanded_list(); |
ysr@777 | 422 | } |
ysr@777 | 423 | } |
ysr@777 | 424 | |
ysr@777 | 425 | |
ysr@777 | 426 | SparsePRT::SparsePRT(HeapRegion* hr) : |
ysr@777 | 427 | _expanded(false), _next_expanded(NULL) |
ysr@777 | 428 | { |
ysr@777 | 429 | _cur = new RSHashTable(InitialCapacity); |
ysr@777 | 430 | _next = _cur; |
ysr@777 | 431 | } |
ysr@777 | 432 | |
johnc@1242 | 433 | |
ysr@777 | 434 | SparsePRT::~SparsePRT() { |
ysr@777 | 435 | assert(_next != NULL && _cur != NULL, "Inv"); |
ysr@777 | 436 | if (_cur != _next) { delete _cur; } |
ysr@777 | 437 | delete _next; |
ysr@777 | 438 | } |
ysr@777 | 439 | |
ysr@777 | 440 | |
ysr@777 | 441 | size_t SparsePRT::mem_size() const { |
ysr@777 | 442 | // We ignore "_cur" here, because it either = _next, or else it is |
ysr@777 | 443 | // on the deleted list. |
ysr@777 | 444 | return sizeof(this) + _next->mem_size(); |
ysr@777 | 445 | } |
ysr@777 | 446 | |
johnc@1242 | 447 | bool SparsePRT::add_card(RegionIdx_t region_id, CardIdx_t card_index) { |
ysr@777 | 448 | #if SPARSE_PRT_VERBOSE |
ysr@777 | 449 | gclog_or_tty->print_cr(" Adding card %d from region %d to region %d sparse.", |
ysr@777 | 450 | card_index, region_id, _hr->hrs_index()); |
ysr@777 | 451 | #endif |
ysr@777 | 452 | if (_next->occupied_entries() * 2 > _next->capacity()) { |
ysr@777 | 453 | expand(); |
ysr@777 | 454 | } |
ysr@777 | 455 | return _next->add_card(region_id, card_index); |
ysr@777 | 456 | } |
ysr@777 | 457 | |
johnc@1242 | 458 | bool SparsePRT::get_cards(RegionIdx_t region_id, CardIdx_t* cards) { |
ysr@777 | 459 | return _next->get_cards(region_id, cards); |
ysr@777 | 460 | } |
ysr@777 | 461 | |
iveresov@1696 | 462 | SparsePRTEntry* SparsePRT::get_entry(RegionIdx_t region_id) { |
iveresov@1696 | 463 | return _next->get_entry(region_id); |
iveresov@1696 | 464 | } |
iveresov@1696 | 465 | |
johnc@1242 | 466 | bool SparsePRT::delete_entry(RegionIdx_t region_id) { |
ysr@777 | 467 | return _next->delete_entry(region_id); |
ysr@777 | 468 | } |
ysr@777 | 469 | |
ysr@777 | 470 | void SparsePRT::clear() { |
ysr@777 | 471 | // If they differ, _next is bigger then cur, so next has no chance of |
ysr@777 | 472 | // being the initial size. |
ysr@777 | 473 | if (_next != _cur) { |
ysr@777 | 474 | delete _next; |
ysr@777 | 475 | } |
ysr@777 | 476 | |
ysr@777 | 477 | if (_cur->capacity() != InitialCapacity) { |
ysr@777 | 478 | delete _cur; |
ysr@777 | 479 | _cur = new RSHashTable(InitialCapacity); |
ysr@777 | 480 | } else { |
ysr@777 | 481 | _cur->clear(); |
ysr@777 | 482 | } |
ysr@777 | 483 | _next = _cur; |
ysr@777 | 484 | } |
ysr@777 | 485 | |
ysr@777 | 486 | void SparsePRT::cleanup() { |
apetrusenko@1480 | 487 | // Make sure that the current and next tables agree. |
apetrusenko@1480 | 488 | if (_cur != _next) { |
apetrusenko@1480 | 489 | delete _cur; |
apetrusenko@1480 | 490 | } |
ysr@777 | 491 | _cur = _next; |
tonyp@1052 | 492 | set_expanded(false); |
ysr@777 | 493 | } |
ysr@777 | 494 | |
ysr@777 | 495 | void SparsePRT::expand() { |
ysr@777 | 496 | RSHashTable* last = _next; |
ysr@777 | 497 | _next = new RSHashTable(last->capacity() * 2); |
ysr@777 | 498 | |
ysr@777 | 499 | #if SPARSE_PRT_VERBOSE |
ysr@777 | 500 | gclog_or_tty->print_cr(" Expanded sparse table for %d to %d.", |
ysr@777 | 501 | _hr->hrs_index(), _next->capacity()); |
ysr@777 | 502 | #endif |
ysr@777 | 503 | for (size_t i = 0; i < last->capacity(); i++) { |
ysr@777 | 504 | SparsePRTEntry* e = last->entry((int)i); |
ysr@777 | 505 | if (e->valid_entry()) { |
ysr@777 | 506 | #if SPARSE_PRT_VERBOSE |
ysr@777 | 507 | gclog_or_tty->print_cr(" During expansion, transferred entry for %d.", |
ysr@777 | 508 | e->r_ind()); |
ysr@777 | 509 | #endif |
ysr@777 | 510 | _next->add_entry(e); |
ysr@777 | 511 | } |
ysr@777 | 512 | } |
apetrusenko@1480 | 513 | if (last != _cur) { |
apetrusenko@1480 | 514 | delete last; |
apetrusenko@1480 | 515 | } |
ysr@777 | 516 | add_to_expanded_list(this); |
ysr@777 | 517 | } |