src/share/vm/gc_implementation/g1/sparsePRT.cpp

Sat, 16 Oct 2010 17:12:19 -0400

author
tonyp
date
Sat, 16 Oct 2010 17:12:19 -0400
changeset 2241
72a161e62cc4
parent 2239
9f4848ebbabd
child 2314
f95d63e2154a
permissions
-rw-r--r--

6991377: G1: race between concurrent refinement and humongous object allocation
Summary: There is a race between the concurrent refinement threads and the humongous object allocation that can cause the concurrent refinement threads to corrupt the part of the BOT that it is being initialized by the humongous object allocation operation. The solution is to do the humongous object allocation in careful steps to ensure that the concurrent refinement threads always have a consistent view over the BOT, region contents, and top. The fix includes some very minor tidying up in sparsePRT.
Reviewed-by: jcoomes, johnc, ysr

ysr@777 1 /*
trims@1907 2 * Copyright (c) 2001, 2009, Oracle and/or its affiliates. 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 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * 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
tonyp@2241 311 CardIdx_t 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
tonyp@2241 325 size_t RSHashTableIter::compute_card_ind(CardIdx_t ci) {
tonyp@2239 326 return (_rsht->entry(_bl_ind)->r_ind() * HeapRegion::CardsPerRegion) + ci;
ysr@777 327 }
ysr@777 328
tonyp@2241 329 bool RSHashTableIter::has_next(size_t& card_index) {
ysr@777 330 _card_ind++;
johnc@1242 331 CardIdx_t ci;
iveresov@1696 332 if (_card_ind < SparsePRTEntry::cards_num() &&
ysr@777 333 ((ci = _rsht->entry(_bl_ind)->card(_card_ind)) !=
ysr@777 334 SparsePRTEntry::NullEntry)) {
ysr@777 335 card_index = compute_card_ind(ci);
ysr@777 336 return true;
ysr@777 337 }
ysr@777 338 // Otherwise, must find the next valid entry.
ysr@777 339 _card_ind = 0;
ysr@777 340
ysr@777 341 if (_bl_ind != RSHashTable::NullEntry) {
ysr@777 342 _bl_ind = _rsht->entry(_bl_ind)->next_index();
ysr@777 343 ci = find_first_card_in_list();
ysr@777 344 if (ci != SparsePRTEntry::NullEntry) {
ysr@777 345 card_index = compute_card_ind(ci);
ysr@777 346 return true;
ysr@777 347 }
ysr@777 348 }
ysr@777 349 // If we didn't return above, must go to the next non-null table index.
ysr@777 350 _tbl_ind++;
ysr@777 351 while ((size_t)_tbl_ind < _rsht->capacity()) {
ysr@777 352 _bl_ind = _rsht->_buckets[_tbl_ind];
ysr@777 353 ci = find_first_card_in_list();
ysr@777 354 if (ci != SparsePRTEntry::NullEntry) {
ysr@777 355 card_index = compute_card_ind(ci);
ysr@777 356 return true;
ysr@777 357 }
ysr@777 358 // Otherwise, try next entry.
ysr@777 359 _tbl_ind++;
ysr@777 360 }
ysr@777 361 // Otherwise, there were no entry.
ysr@777 362 return false;
ysr@777 363 }
ysr@777 364
johnc@1242 365 bool RSHashTable::contains_card(RegionIdx_t region_index, CardIdx_t card_index) const {
ysr@777 366 SparsePRTEntry* e = entry_for_region_ind(region_index);
ysr@777 367 return (e != NULL && e->contains_card(card_index));
ysr@777 368 }
ysr@777 369
ysr@777 370 size_t RSHashTable::mem_size() const {
johnc@1242 371 return sizeof(this) +
iveresov@1696 372 capacity() * (SparsePRTEntry::size() + sizeof(int));
ysr@777 373 }
ysr@777 374
ysr@777 375 // ----------------------------------------------------------------------
ysr@777 376
ysr@777 377 SparsePRT* SparsePRT::_head_expanded_list = NULL;
ysr@777 378
ysr@777 379 void SparsePRT::add_to_expanded_list(SparsePRT* sprt) {
ysr@777 380 // We could expand multiple times in a pause -- only put on list once.
ysr@777 381 if (sprt->expanded()) return;
ysr@777 382 sprt->set_expanded(true);
ysr@777 383 SparsePRT* hd = _head_expanded_list;
ysr@777 384 while (true) {
ysr@777 385 sprt->_next_expanded = hd;
ysr@777 386 SparsePRT* res =
ysr@777 387 (SparsePRT*)
ysr@777 388 Atomic::cmpxchg_ptr(sprt, &_head_expanded_list, hd);
ysr@777 389 if (res == hd) return;
ysr@777 390 else hd = res;
ysr@777 391 }
ysr@777 392 }
ysr@777 393
johnc@1242 394
ysr@777 395 SparsePRT* SparsePRT::get_from_expanded_list() {
ysr@777 396 SparsePRT* hd = _head_expanded_list;
ysr@777 397 while (hd != NULL) {
ysr@777 398 SparsePRT* next = hd->next_expanded();
ysr@777 399 SparsePRT* res =
ysr@777 400 (SparsePRT*)
ysr@777 401 Atomic::cmpxchg_ptr(next, &_head_expanded_list, hd);
ysr@777 402 if (res == hd) {
ysr@777 403 hd->set_next_expanded(NULL);
ysr@777 404 return hd;
ysr@777 405 } else {
ysr@777 406 hd = res;
ysr@777 407 }
ysr@777 408 }
ysr@777 409 return NULL;
ysr@777 410 }
ysr@777 411
ysr@777 412
ysr@777 413 void SparsePRT::cleanup_all() {
ysr@777 414 // First clean up all expanded tables so they agree on next and cur.
ysr@777 415 SparsePRT* sprt = get_from_expanded_list();
ysr@777 416 while (sprt != NULL) {
ysr@777 417 sprt->cleanup();
ysr@777 418 sprt = get_from_expanded_list();
ysr@777 419 }
ysr@777 420 }
ysr@777 421
ysr@777 422
ysr@777 423 SparsePRT::SparsePRT(HeapRegion* hr) :
johnc@2063 424 _hr(hr), _expanded(false), _next_expanded(NULL)
ysr@777 425 {
ysr@777 426 _cur = new RSHashTable(InitialCapacity);
ysr@777 427 _next = _cur;
ysr@777 428 }
ysr@777 429
johnc@1242 430
ysr@777 431 SparsePRT::~SparsePRT() {
ysr@777 432 assert(_next != NULL && _cur != NULL, "Inv");
ysr@777 433 if (_cur != _next) { delete _cur; }
ysr@777 434 delete _next;
ysr@777 435 }
ysr@777 436
ysr@777 437
ysr@777 438 size_t SparsePRT::mem_size() const {
ysr@777 439 // We ignore "_cur" here, because it either = _next, or else it is
ysr@777 440 // on the deleted list.
ysr@777 441 return sizeof(this) + _next->mem_size();
ysr@777 442 }
ysr@777 443
johnc@1242 444 bool SparsePRT::add_card(RegionIdx_t region_id, CardIdx_t card_index) {
ysr@777 445 #if SPARSE_PRT_VERBOSE
ysr@777 446 gclog_or_tty->print_cr(" Adding card %d from region %d to region %d sparse.",
ysr@777 447 card_index, region_id, _hr->hrs_index());
ysr@777 448 #endif
ysr@777 449 if (_next->occupied_entries() * 2 > _next->capacity()) {
ysr@777 450 expand();
ysr@777 451 }
ysr@777 452 return _next->add_card(region_id, card_index);
ysr@777 453 }
ysr@777 454
johnc@1242 455 bool SparsePRT::get_cards(RegionIdx_t region_id, CardIdx_t* cards) {
ysr@777 456 return _next->get_cards(region_id, cards);
ysr@777 457 }
ysr@777 458
iveresov@1696 459 SparsePRTEntry* SparsePRT::get_entry(RegionIdx_t region_id) {
iveresov@1696 460 return _next->get_entry(region_id);
iveresov@1696 461 }
iveresov@1696 462
johnc@1242 463 bool SparsePRT::delete_entry(RegionIdx_t region_id) {
ysr@777 464 return _next->delete_entry(region_id);
ysr@777 465 }
ysr@777 466
ysr@777 467 void SparsePRT::clear() {
ysr@777 468 // If they differ, _next is bigger then cur, so next has no chance of
ysr@777 469 // being the initial size.
ysr@777 470 if (_next != _cur) {
ysr@777 471 delete _next;
ysr@777 472 }
ysr@777 473
ysr@777 474 if (_cur->capacity() != InitialCapacity) {
ysr@777 475 delete _cur;
ysr@777 476 _cur = new RSHashTable(InitialCapacity);
ysr@777 477 } else {
ysr@777 478 _cur->clear();
ysr@777 479 }
ysr@777 480 _next = _cur;
ysr@777 481 }
ysr@777 482
ysr@777 483 void SparsePRT::cleanup() {
apetrusenko@1480 484 // Make sure that the current and next tables agree.
apetrusenko@1480 485 if (_cur != _next) {
apetrusenko@1480 486 delete _cur;
apetrusenko@1480 487 }
ysr@777 488 _cur = _next;
tonyp@1052 489 set_expanded(false);
ysr@777 490 }
ysr@777 491
ysr@777 492 void SparsePRT::expand() {
ysr@777 493 RSHashTable* last = _next;
ysr@777 494 _next = new RSHashTable(last->capacity() * 2);
ysr@777 495
ysr@777 496 #if SPARSE_PRT_VERBOSE
ysr@777 497 gclog_or_tty->print_cr(" Expanded sparse table for %d to %d.",
ysr@777 498 _hr->hrs_index(), _next->capacity());
ysr@777 499 #endif
ysr@777 500 for (size_t i = 0; i < last->capacity(); i++) {
ysr@777 501 SparsePRTEntry* e = last->entry((int)i);
ysr@777 502 if (e->valid_entry()) {
ysr@777 503 #if SPARSE_PRT_VERBOSE
ysr@777 504 gclog_or_tty->print_cr(" During expansion, transferred entry for %d.",
ysr@777 505 e->r_ind());
ysr@777 506 #endif
ysr@777 507 _next->add_entry(e);
ysr@777 508 }
ysr@777 509 }
apetrusenko@1480 510 if (last != _cur) {
apetrusenko@1480 511 delete last;
apetrusenko@1480 512 }
ysr@777 513 add_to_expanded_list(this);
ysr@777 514 }

mercurial