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

Tue, 21 Aug 2012 14:10:39 -0700

author
johnc
date
Tue, 21 Aug 2012 14:10:39 -0700
changeset 3998
7383557659bd
parent 3900
d2a62e0f25eb
child 5014
5c93c1f61226
permissions
-rw-r--r--

7185699: G1: Prediction model discrepancies
Summary: Correct the result value of G1CollectedHeap::pending_card_num(). Change the code that calculates the GC efficiency of a non-young heap region to use historical data from mixed GCs and the actual number of live bytes when predicting how long it would take to collect the region. Changes were also reviewed by Thomas Schatzl.
Reviewed-by: azeemj, brutisso

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

mercurial