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

Fri, 10 Oct 2014 15:51:58 +0200

author
tschatzl
date
Fri, 10 Oct 2014 15:51:58 +0200
changeset 7257
e7d0505c8a30
parent 7091
a8ea2f110d87
child 7535
7ae4e26cb1e0
permissions
-rw-r--r--

8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso

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

mercurial