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

Mon, 03 Aug 2009 12:59:30 -0700

author
johnc
date
Mon, 03 Aug 2009 12:59:30 -0700
changeset 1324
15c5903cf9e1
parent 1279
bd02caa94611
child 1377
2c79770d1f6e
permissions
-rw-r--r--

6865703: G1: Parallelize hot card cache cleanup
Summary: Have the GC worker threads clear the hot card cache in parallel by having each worker thread claim a chunk of the card cache and process the cards in that chunk. The size of the chunks that each thread will claim is determined at VM initialization from the size of the card cache and the number of worker threads.
Reviewed-by: jmasa, tonyp

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

mercurial