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

Fri, 10 Jun 2011 13:16:40 -0400

author
tonyp
date
Fri, 10 Jun 2011 13:16:40 -0400
changeset 2963
c3f1170908be
parent 2493
97ba643ea3ed
child 3713
720b6a76dd9d
permissions
-rw-r--r--

7045330: G1: Simplify/fix the HeapRegionSeq class
7042285: G1: native memory leak during humongous object allocation
6804436: G1: heap region indices should be size_t
Summary: A series of fixes and improvements to the HeapRegionSeq class: a) replace the _regions growable array with a standard C array, b) avoid de-allocating / re-allocating HeapRegion instances when the heap shrinks / grows (fix for 7042285), c) introduce fast method to map address to HeapRegion via a "biased" array pointer, d) embed the _hrs object in G1CollectedHeap, instead of pointing to it via an indirection, e) assume that all the regions added to the HeapRegionSeq instance are contiguous, f) replace int's with size_t's for indexes (and expand that to HeapRegion as part of 6804436), g) remove unnecessary / unused methods, h) rename a couple of fields (_alloc_search_start and _seq_bottom), i) fix iterate_from() not to always start from index 0 irrespective of the region passed to it, j) add a verification method to check the HeapRegionSeq assumptions, k) always call the wrappers for _hrs.iterate(), _hrs_length(), and _hrs.at() from G1CollectedHeap, not those methods directly, and l) unify the code that expands the sequence (by either re-using or creating a new HeapRegion) and make it robust wrt to a HeapRegion allocation failing.
Reviewed-by: stefank, johnc, brutisso

ysr@777 1 /*
tonyp@2493 2 * Copyright (c) 2001, 2011, 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),
iveresov@1696 151 _entries((SparsePRTEntry*)NEW_C_HEAP_ARRAY(char, SparsePRTEntry::size() * capacity)),
johnc@1242 152 _buckets(NEW_C_HEAP_ARRAY(int, capacity)),
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) {
ysr@777 160 FREE_C_HEAP_ARRAY(SparsePRTEntry, _entries);
ysr@777 161 _entries = NULL;
ysr@777 162 }
ysr@777 163 if (_buckets != NULL) {
johnc@1242 164 FREE_C_HEAP_ARRAY(int, _buckets);
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@2963 484 gclog_or_tty->print_cr(" Adding card %d from region %d to region "
tonyp@2963 485 SIZE_FORMAT" sparse.",
tonyp@2963 486 card_index, region_id, _hr->hrs_index());
ysr@777 487 #endif
ysr@777 488 if (_next->occupied_entries() * 2 > _next->capacity()) {
ysr@777 489 expand();
ysr@777 490 }
ysr@777 491 return _next->add_card(region_id, card_index);
ysr@777 492 }
ysr@777 493
johnc@1242 494 bool SparsePRT::get_cards(RegionIdx_t region_id, CardIdx_t* cards) {
ysr@777 495 return _next->get_cards(region_id, cards);
ysr@777 496 }
ysr@777 497
iveresov@1696 498 SparsePRTEntry* SparsePRT::get_entry(RegionIdx_t region_id) {
iveresov@1696 499 return _next->get_entry(region_id);
iveresov@1696 500 }
iveresov@1696 501
johnc@1242 502 bool SparsePRT::delete_entry(RegionIdx_t region_id) {
ysr@777 503 return _next->delete_entry(region_id);
ysr@777 504 }
ysr@777 505
ysr@777 506 void SparsePRT::clear() {
ysr@777 507 // If they differ, _next is bigger then cur, so next has no chance of
ysr@777 508 // being the initial size.
ysr@777 509 if (_next != _cur) {
ysr@777 510 delete _next;
ysr@777 511 }
ysr@777 512
ysr@777 513 if (_cur->capacity() != InitialCapacity) {
ysr@777 514 delete _cur;
ysr@777 515 _cur = new RSHashTable(InitialCapacity);
ysr@777 516 } else {
ysr@777 517 _cur->clear();
ysr@777 518 }
ysr@777 519 _next = _cur;
tonyp@2493 520 _expanded = false;
ysr@777 521 }
ysr@777 522
ysr@777 523 void SparsePRT::cleanup() {
apetrusenko@1480 524 // Make sure that the current and next tables agree.
apetrusenko@1480 525 if (_cur != _next) {
apetrusenko@1480 526 delete _cur;
apetrusenko@1480 527 }
ysr@777 528 _cur = _next;
tonyp@1052 529 set_expanded(false);
ysr@777 530 }
ysr@777 531
ysr@777 532 void SparsePRT::expand() {
ysr@777 533 RSHashTable* last = _next;
ysr@777 534 _next = new RSHashTable(last->capacity() * 2);
ysr@777 535
ysr@777 536 #if SPARSE_PRT_VERBOSE
tonyp@2963 537 gclog_or_tty->print_cr(" Expanded sparse table for "SIZE_FORMAT" to %d.",
tonyp@2963 538 _hr->hrs_index(), _next->capacity());
ysr@777 539 #endif
ysr@777 540 for (size_t i = 0; i < last->capacity(); i++) {
ysr@777 541 SparsePRTEntry* e = last->entry((int)i);
ysr@777 542 if (e->valid_entry()) {
ysr@777 543 #if SPARSE_PRT_VERBOSE
ysr@777 544 gclog_or_tty->print_cr(" During expansion, transferred entry for %d.",
ysr@777 545 e->r_ind());
ysr@777 546 #endif
ysr@777 547 _next->add_entry(e);
ysr@777 548 }
ysr@777 549 }
apetrusenko@1480 550 if (last != _cur) {
apetrusenko@1480 551 delete last;
apetrusenko@1480 552 }
ysr@777 553 add_to_expanded_list(this);
ysr@777 554 }
tonyp@2493 555
tonyp@2493 556 void SparsePRTCleanupTask::add(SparsePRT* sprt) {
tonyp@2493 557 assert(sprt->should_be_on_expanded_list(), "pre-condition");
tonyp@2493 558
tonyp@2493 559 sprt->set_next_expanded(NULL);
tonyp@2493 560 if (_tail != NULL) {
tonyp@2493 561 _tail->set_next_expanded(sprt);
tonyp@2493 562 } else {
tonyp@2493 563 _head = sprt;
tonyp@2493 564 }
tonyp@2493 565 _tail = sprt;
tonyp@2493 566 }

mercurial