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

Wed, 27 Apr 2016 01:25:04 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:25:04 +0800
changeset 0
f90c822e73f8
child 6876
710a3c8b516e
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/
changeset: 6782:28b50d07f6f8
tag: jdk8u25-b17

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

mercurial