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

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

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

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

ysr@777 1 /*
xdono@1014 2 * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
ysr@777 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ysr@777 4 *
ysr@777 5 * This code is free software; you can redistribute it and/or modify it
ysr@777 6 * under the terms of the GNU General Public License version 2 only, as
ysr@777 7 * published by the Free Software Foundation.
ysr@777 8 *
ysr@777 9 * This code is distributed in the hope that it will be useful, but WITHOUT
ysr@777 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ysr@777 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ysr@777 12 * version 2 for more details (a copy is included in the LICENSE file that
ysr@777 13 * accompanied this code).
ysr@777 14 *
ysr@777 15 * You should have received a copy of the GNU General Public License version
ysr@777 16 * 2 along with this work; if not, write to the Free Software Foundation,
ysr@777 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ysr@777 18 *
ysr@777 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
ysr@777 20 * CA 95054 USA or visit www.sun.com if you need additional information or
ysr@777 21 * have any questions.
ysr@777 22 *
ysr@777 23 */
ysr@777 24
ysr@777 25 #include "incls/_precompiled.incl"
ysr@777 26 #include "incls/_heapRegionRemSet.cpp.incl"
ysr@777 27
ysr@777 28 #define HRRS_VERBOSE 0
ysr@777 29
ysr@777 30 #define PRT_COUNT_OCCUPIED 1
ysr@777 31
ysr@777 32 // OtherRegionsTable
ysr@777 33
ysr@777 34 class PerRegionTable: public CHeapObj {
ysr@777 35 friend class OtherRegionsTable;
ysr@777 36 friend class HeapRegionRemSetIterator;
ysr@777 37
ysr@777 38 HeapRegion* _hr;
ysr@777 39 BitMap _bm;
ysr@777 40 #if PRT_COUNT_OCCUPIED
ysr@777 41 jint _occupied;
ysr@777 42 #endif
ysr@777 43 PerRegionTable* _next_free;
ysr@777 44
ysr@777 45 PerRegionTable* next_free() { return _next_free; }
ysr@777 46 void set_next_free(PerRegionTable* prt) { _next_free = prt; }
ysr@777 47
ysr@777 48
ysr@777 49 static PerRegionTable* _free_list;
ysr@777 50
ysr@777 51 #ifdef _MSC_VER
ysr@777 52 // For some reason even though the classes are marked as friend they are unable
ysr@777 53 // to access CardsPerRegion when private/protected. Only the windows c++ compiler
ysr@777 54 // says this Sun CC and linux gcc don't have a problem with access when private
ysr@777 55
ysr@777 56 public:
ysr@777 57
ysr@777 58 #endif // _MSC_VER
ysr@777 59
ysr@777 60 enum SomePrivateConstants {
ysr@777 61 CardsPerRegion = HeapRegion::GrainBytes >> CardTableModRefBS::card_shift
ysr@777 62 };
ysr@777 63
ysr@777 64 protected:
ysr@777 65 // We need access in order to union things into the base table.
ysr@777 66 BitMap* bm() { return &_bm; }
ysr@777 67
apetrusenko@980 68 #if PRT_COUNT_OCCUPIED
ysr@777 69 void recount_occupied() {
ysr@777 70 _occupied = (jint) bm()->count_one_bits();
ysr@777 71 }
apetrusenko@980 72 #endif
ysr@777 73
ysr@777 74 PerRegionTable(HeapRegion* hr) :
ysr@777 75 _hr(hr),
ysr@777 76 #if PRT_COUNT_OCCUPIED
ysr@777 77 _occupied(0),
ysr@777 78 #endif
ysr@777 79 _bm(CardsPerRegion, false /* in-resource-area */)
ysr@777 80 {}
ysr@777 81
ysr@777 82 static void free(PerRegionTable* prt) {
ysr@777 83 while (true) {
ysr@777 84 PerRegionTable* fl = _free_list;
ysr@777 85 prt->set_next_free(fl);
ysr@777 86 PerRegionTable* res =
ysr@777 87 (PerRegionTable*)
ysr@777 88 Atomic::cmpxchg_ptr(prt, &_free_list, fl);
ysr@777 89 if (res == fl) return;
ysr@777 90 }
ysr@777 91 ShouldNotReachHere();
ysr@777 92 }
ysr@777 93
ysr@777 94 static PerRegionTable* alloc(HeapRegion* hr) {
ysr@777 95 PerRegionTable* fl = _free_list;
ysr@777 96 while (fl != NULL) {
ysr@777 97 PerRegionTable* nxt = fl->next_free();
ysr@777 98 PerRegionTable* res =
ysr@777 99 (PerRegionTable*)
ysr@777 100 Atomic::cmpxchg_ptr(nxt, &_free_list, fl);
ysr@777 101 if (res == fl) {
ysr@777 102 fl->init(hr);
ysr@777 103 return fl;
ysr@777 104 } else {
ysr@777 105 fl = _free_list;
ysr@777 106 }
ysr@777 107 }
ysr@777 108 assert(fl == NULL, "Loop condition.");
ysr@777 109 return new PerRegionTable(hr);
ysr@777 110 }
ysr@777 111
johnc@1242 112 void add_card_work(CardIdx_t from_card, bool par) {
ysr@777 113 if (!_bm.at(from_card)) {
ysr@777 114 if (par) {
ysr@777 115 if (_bm.par_at_put(from_card, 1)) {
ysr@777 116 #if PRT_COUNT_OCCUPIED
ysr@777 117 Atomic::inc(&_occupied);
ysr@777 118 #endif
ysr@777 119 }
ysr@777 120 } else {
ysr@777 121 _bm.at_put(from_card, 1);
ysr@777 122 #if PRT_COUNT_OCCUPIED
ysr@777 123 _occupied++;
ysr@777 124 #endif
ysr@777 125 }
ysr@777 126 }
ysr@777 127 }
ysr@777 128
ysr@1280 129 void add_reference_work(OopOrNarrowOopStar from, bool par) {
ysr@777 130 // Must make this robust in case "from" is not in "_hr", because of
ysr@777 131 // concurrency.
ysr@777 132
ysr@777 133 #if HRRS_VERBOSE
ysr@777 134 gclog_or_tty->print_cr(" PRT::Add_reference_work(" PTR_FORMAT "->" PTR_FORMAT").",
ysr@777 135 from, *from);
ysr@777 136 #endif
ysr@777 137
ysr@777 138 HeapRegion* loc_hr = hr();
ysr@777 139 // If the test below fails, then this table was reused concurrently
ysr@777 140 // with this operation. This is OK, since the old table was coarsened,
ysr@777 141 // and adding a bit to the new table is never incorrect.
ysr@777 142 if (loc_hr->is_in_reserved(from)) {
ysr@777 143 size_t hw_offset = pointer_delta((HeapWord*)from, loc_hr->bottom());
johnc@1242 144 CardIdx_t from_card = (CardIdx_t)
johnc@1242 145 hw_offset >> (CardTableModRefBS::card_shift - LogHeapWordSize);
ysr@777 146
johnc@1242 147 assert(0 <= from_card && from_card < CardsPerRegion, "Must be in range.");
johnc@1242 148 add_card_work(from_card, par);
ysr@777 149 }
ysr@777 150 }
ysr@777 151
ysr@777 152 public:
ysr@777 153
ysr@777 154 HeapRegion* hr() const { return _hr; }
ysr@777 155
ysr@777 156 #if PRT_COUNT_OCCUPIED
ysr@777 157 jint occupied() const {
ysr@777 158 // Overkill, but if we ever need it...
ysr@777 159 // guarantee(_occupied == _bm.count_one_bits(), "Check");
ysr@777 160 return _occupied;
ysr@777 161 }
ysr@777 162 #else
ysr@777 163 jint occupied() const {
ysr@777 164 return _bm.count_one_bits();
ysr@777 165 }
ysr@777 166 #endif
ysr@777 167
ysr@777 168 void init(HeapRegion* hr) {
ysr@777 169 _hr = hr;
ysr@777 170 #if PRT_COUNT_OCCUPIED
ysr@777 171 _occupied = 0;
ysr@777 172 #endif
ysr@777 173 _bm.clear();
ysr@777 174 }
ysr@777 175
ysr@1280 176 void add_reference(OopOrNarrowOopStar from) {
ysr@777 177 add_reference_work(from, /*parallel*/ true);
ysr@777 178 }
ysr@777 179
ysr@1280 180 void seq_add_reference(OopOrNarrowOopStar from) {
ysr@777 181 add_reference_work(from, /*parallel*/ false);
ysr@777 182 }
ysr@777 183
ysr@777 184 void scrub(CardTableModRefBS* ctbs, BitMap* card_bm) {
ysr@777 185 HeapWord* hr_bot = hr()->bottom();
swamyv@924 186 size_t hr_first_card_index = ctbs->index_for(hr_bot);
ysr@777 187 bm()->set_intersection_at_offset(*card_bm, hr_first_card_index);
ysr@777 188 #if PRT_COUNT_OCCUPIED
ysr@777 189 recount_occupied();
ysr@777 190 #endif
ysr@777 191 }
ysr@777 192
johnc@1242 193 void add_card(CardIdx_t from_card_index) {
ysr@777 194 add_card_work(from_card_index, /*parallel*/ true);
ysr@777 195 }
ysr@777 196
johnc@1242 197 void seq_add_card(CardIdx_t from_card_index) {
ysr@777 198 add_card_work(from_card_index, /*parallel*/ false);
ysr@777 199 }
ysr@777 200
ysr@777 201 // (Destructively) union the bitmap of the current table into the given
ysr@777 202 // bitmap (which is assumed to be of the same size.)
ysr@777 203 void union_bitmap_into(BitMap* bm) {
ysr@777 204 bm->set_union(_bm);
ysr@777 205 }
ysr@777 206
ysr@777 207 // Mem size in bytes.
ysr@777 208 size_t mem_size() const {
ysr@777 209 return sizeof(this) + _bm.size_in_words() * HeapWordSize;
ysr@777 210 }
ysr@777 211
ysr@777 212 static size_t fl_mem_size() {
ysr@777 213 PerRegionTable* cur = _free_list;
ysr@777 214 size_t res = 0;
ysr@777 215 while (cur != NULL) {
ysr@777 216 res += sizeof(PerRegionTable);
ysr@777 217 cur = cur->next_free();
ysr@777 218 }
ysr@777 219 return res;
ysr@777 220 }
ysr@777 221
ysr@777 222 // Requires "from" to be in "hr()".
ysr@1280 223 bool contains_reference(OopOrNarrowOopStar from) const {
ysr@777 224 assert(hr()->is_in_reserved(from), "Precondition.");
ysr@777 225 size_t card_ind = pointer_delta(from, hr()->bottom(),
ysr@777 226 CardTableModRefBS::card_size);
ysr@777 227 return _bm.at(card_ind);
ysr@777 228 }
ysr@777 229 };
ysr@777 230
ysr@777 231 PerRegionTable* PerRegionTable::_free_list = NULL;
ysr@777 232
ysr@777 233
ysr@777 234 #define COUNT_PAR_EXPANDS 0
ysr@777 235
ysr@777 236 #if COUNT_PAR_EXPANDS
ysr@777 237 static jint n_par_expands = 0;
ysr@777 238 static jint n_par_contracts = 0;
ysr@777 239 static jint par_expand_list_len = 0;
ysr@777 240 static jint max_par_expand_list_len = 0;
ysr@777 241
ysr@777 242 static void print_par_expand() {
ysr@777 243 Atomic::inc(&n_par_expands);
ysr@777 244 Atomic::inc(&par_expand_list_len);
ysr@777 245 if (par_expand_list_len > max_par_expand_list_len) {
ysr@777 246 max_par_expand_list_len = par_expand_list_len;
ysr@777 247 }
ysr@777 248 if ((n_par_expands % 10) == 0) {
ysr@777 249 gclog_or_tty->print_cr("\n\n%d par expands: %d contracts, "
ysr@777 250 "len = %d, max_len = %d\n.",
ysr@777 251 n_par_expands, n_par_contracts, par_expand_list_len,
ysr@777 252 max_par_expand_list_len);
ysr@777 253 }
ysr@777 254 }
ysr@777 255 #endif
ysr@777 256
ysr@777 257 class PosParPRT: public PerRegionTable {
ysr@777 258 PerRegionTable** _par_tables;
ysr@777 259
ysr@777 260 enum SomePrivateConstants {
ysr@777 261 ReserveParTableExpansion = 1
ysr@777 262 };
ysr@777 263
ysr@777 264 void par_expand() {
ysr@777 265 int n = HeapRegionRemSet::num_par_rem_sets()-1;
ysr@777 266 if (n <= 0) return;
ysr@777 267 if (_par_tables == NULL) {
ysr@777 268 PerRegionTable* res =
ysr@777 269 (PerRegionTable*)
ysr@777 270 Atomic::cmpxchg_ptr((PerRegionTable*)ReserveParTableExpansion,
ysr@777 271 &_par_tables, NULL);
ysr@777 272 if (res != NULL) return;
ysr@777 273 // Otherwise, we reserved the right to do the expansion.
ysr@777 274
ysr@777 275 PerRegionTable** ptables = NEW_C_HEAP_ARRAY(PerRegionTable*, n);
ysr@777 276 for (int i = 0; i < n; i++) {
ysr@777 277 PerRegionTable* ptable = PerRegionTable::alloc(hr());
ysr@777 278 ptables[i] = ptable;
ysr@777 279 }
ysr@777 280 // Here we do not need an atomic.
ysr@777 281 _par_tables = ptables;
ysr@777 282 #if COUNT_PAR_EXPANDS
ysr@777 283 print_par_expand();
ysr@777 284 #endif
ysr@777 285 // We must put this table on the expanded list.
ysr@777 286 PosParPRT* exp_head = _par_expanded_list;
ysr@777 287 while (true) {
ysr@777 288 set_next_par_expanded(exp_head);
ysr@777 289 PosParPRT* res =
ysr@777 290 (PosParPRT*)
ysr@777 291 Atomic::cmpxchg_ptr(this, &_par_expanded_list, exp_head);
ysr@777 292 if (res == exp_head) return;
ysr@777 293 // Otherwise.
ysr@777 294 exp_head = res;
ysr@777 295 }
ysr@777 296 ShouldNotReachHere();
ysr@777 297 }
ysr@777 298 }
ysr@777 299
ysr@777 300 void par_contract() {
ysr@777 301 assert(_par_tables != NULL, "Precondition.");
ysr@777 302 int n = HeapRegionRemSet::num_par_rem_sets()-1;
ysr@777 303 for (int i = 0; i < n; i++) {
ysr@777 304 _par_tables[i]->union_bitmap_into(bm());
ysr@777 305 PerRegionTable::free(_par_tables[i]);
ysr@777 306 _par_tables[i] = NULL;
ysr@777 307 }
ysr@777 308 #if PRT_COUNT_OCCUPIED
ysr@777 309 // We must recount the "occupied."
ysr@777 310 recount_occupied();
ysr@777 311 #endif
ysr@777 312 FREE_C_HEAP_ARRAY(PerRegionTable*, _par_tables);
ysr@777 313 _par_tables = NULL;
ysr@777 314 #if COUNT_PAR_EXPANDS
ysr@777 315 Atomic::inc(&n_par_contracts);
ysr@777 316 Atomic::dec(&par_expand_list_len);
ysr@777 317 #endif
ysr@777 318 }
ysr@777 319
ysr@777 320 static PerRegionTable** _par_table_fl;
ysr@777 321
ysr@777 322 PosParPRT* _next;
ysr@777 323
ysr@777 324 static PosParPRT* _free_list;
ysr@777 325
ysr@777 326 PerRegionTable** par_tables() const {
ysr@777 327 assert(uintptr_t(NULL) == 0, "Assumption.");
ysr@777 328 if (uintptr_t(_par_tables) <= ReserveParTableExpansion)
ysr@777 329 return NULL;
ysr@777 330 else
ysr@777 331 return _par_tables;
ysr@777 332 }
ysr@777 333
ysr@777 334 PosParPRT* _next_par_expanded;
ysr@777 335 PosParPRT* next_par_expanded() { return _next_par_expanded; }
ysr@777 336 void set_next_par_expanded(PosParPRT* ppprt) { _next_par_expanded = ppprt; }
ysr@777 337 static PosParPRT* _par_expanded_list;
ysr@777 338
ysr@777 339 public:
ysr@777 340
ysr@777 341 PosParPRT(HeapRegion* hr) : PerRegionTable(hr), _par_tables(NULL) {}
ysr@777 342
ysr@777 343 jint occupied() const {
ysr@777 344 jint res = PerRegionTable::occupied();
ysr@777 345 if (par_tables() != NULL) {
ysr@777 346 for (int i = 0; i < HeapRegionRemSet::num_par_rem_sets()-1; i++) {
ysr@777 347 res += par_tables()[i]->occupied();
ysr@777 348 }
ysr@777 349 }
ysr@777 350 return res;
ysr@777 351 }
ysr@777 352
ysr@777 353 void init(HeapRegion* hr) {
ysr@777 354 PerRegionTable::init(hr);
ysr@777 355 _next = NULL;
ysr@777 356 if (par_tables() != NULL) {
ysr@777 357 for (int i = 0; i < HeapRegionRemSet::num_par_rem_sets()-1; i++) {
ysr@777 358 par_tables()[i]->init(hr);
ysr@777 359 }
ysr@777 360 }
ysr@777 361 }
ysr@777 362
ysr@777 363 static void free(PosParPRT* prt) {
ysr@777 364 while (true) {
ysr@777 365 PosParPRT* fl = _free_list;
ysr@777 366 prt->set_next(fl);
ysr@777 367 PosParPRT* res =
ysr@777 368 (PosParPRT*)
ysr@777 369 Atomic::cmpxchg_ptr(prt, &_free_list, fl);
ysr@777 370 if (res == fl) return;
ysr@777 371 }
ysr@777 372 ShouldNotReachHere();
ysr@777 373 }
ysr@777 374
ysr@777 375 static PosParPRT* alloc(HeapRegion* hr) {
ysr@777 376 PosParPRT* fl = _free_list;
ysr@777 377 while (fl != NULL) {
ysr@777 378 PosParPRT* nxt = fl->next();
ysr@777 379 PosParPRT* res =
ysr@777 380 (PosParPRT*)
ysr@777 381 Atomic::cmpxchg_ptr(nxt, &_free_list, fl);
ysr@777 382 if (res == fl) {
ysr@777 383 fl->init(hr);
ysr@777 384 return fl;
ysr@777 385 } else {
ysr@777 386 fl = _free_list;
ysr@777 387 }
ysr@777 388 }
ysr@777 389 assert(fl == NULL, "Loop condition.");
ysr@777 390 return new PosParPRT(hr);
ysr@777 391 }
ysr@777 392
ysr@777 393 PosParPRT* next() const { return _next; }
ysr@777 394 void set_next(PosParPRT* nxt) { _next = nxt; }
ysr@777 395 PosParPRT** next_addr() { return &_next; }
ysr@777 396
ysr@1280 397 void add_reference(OopOrNarrowOopStar from, int tid) {
ysr@777 398 // Expand if necessary.
ysr@777 399 PerRegionTable** pt = par_tables();
ysr@777 400 if (par_tables() == NULL && tid > 0 && hr()->is_gc_alloc_region()) {
ysr@777 401 par_expand();
ysr@777 402 pt = par_tables();
ysr@777 403 }
ysr@777 404 if (pt != NULL) {
ysr@777 405 // We always have to assume that mods to table 0 are in parallel,
ysr@777 406 // because of the claiming scheme in parallel expansion. A thread
ysr@777 407 // with tid != 0 that finds the table to be NULL, but doesn't succeed
ysr@777 408 // in claiming the right of expanding it, will end up in the else
ysr@777 409 // clause of the above if test. That thread could be delayed, and a
ysr@777 410 // thread 0 add reference could see the table expanded, and come
ysr@777 411 // here. Both threads would be adding in parallel. But we get to
ysr@777 412 // not use atomics for tids > 0.
ysr@777 413 if (tid == 0) {
ysr@777 414 PerRegionTable::add_reference(from);
ysr@777 415 } else {
ysr@777 416 pt[tid-1]->seq_add_reference(from);
ysr@777 417 }
ysr@777 418 } else {
ysr@777 419 // Not expanded -- add to the base table.
ysr@777 420 PerRegionTable::add_reference(from);
ysr@777 421 }
ysr@777 422 }
ysr@777 423
ysr@777 424 void scrub(CardTableModRefBS* ctbs, BitMap* card_bm) {
ysr@777 425 assert(_par_tables == NULL, "Precondition");
ysr@777 426 PerRegionTable::scrub(ctbs, card_bm);
ysr@777 427 }
ysr@777 428
ysr@777 429 size_t mem_size() const {
ysr@777 430 size_t res =
ysr@777 431 PerRegionTable::mem_size() + sizeof(this) - sizeof(PerRegionTable);
ysr@777 432 if (_par_tables != NULL) {
ysr@777 433 for (int i = 0; i < HeapRegionRemSet::num_par_rem_sets()-1; i++) {
ysr@777 434 res += _par_tables[i]->mem_size();
ysr@777 435 }
ysr@777 436 }
ysr@777 437 return res;
ysr@777 438 }
ysr@777 439
ysr@777 440 static size_t fl_mem_size() {
ysr@777 441 PosParPRT* cur = _free_list;
ysr@777 442 size_t res = 0;
ysr@777 443 while (cur != NULL) {
ysr@777 444 res += sizeof(PosParPRT);
ysr@777 445 cur = cur->next();
ysr@777 446 }
ysr@777 447 return res;
ysr@777 448 }
ysr@777 449
ysr@1280 450 bool contains_reference(OopOrNarrowOopStar from) const {
ysr@777 451 if (PerRegionTable::contains_reference(from)) return true;
ysr@777 452 if (_par_tables != NULL) {
ysr@777 453 for (int i = 0; i < HeapRegionRemSet::num_par_rem_sets()-1; i++) {
ysr@777 454 if (_par_tables[i]->contains_reference(from)) return true;
ysr@777 455 }
ysr@777 456 }
ysr@777 457 return false;
ysr@777 458 }
ysr@777 459
ysr@777 460 static void par_contract_all();
ysr@777 461
ysr@777 462 };
ysr@777 463
ysr@777 464 void PosParPRT::par_contract_all() {
ysr@777 465 PosParPRT* hd = _par_expanded_list;
ysr@777 466 while (hd != NULL) {
ysr@777 467 PosParPRT* nxt = hd->next_par_expanded();
ysr@777 468 PosParPRT* res =
ysr@777 469 (PosParPRT*)
ysr@777 470 Atomic::cmpxchg_ptr(nxt, &_par_expanded_list, hd);
ysr@777 471 if (res == hd) {
ysr@777 472 // We claimed the right to contract this table.
ysr@777 473 hd->set_next_par_expanded(NULL);
ysr@777 474 hd->par_contract();
ysr@777 475 hd = _par_expanded_list;
ysr@777 476 } else {
ysr@777 477 hd = res;
ysr@777 478 }
ysr@777 479 }
ysr@777 480 }
ysr@777 481
ysr@777 482 PosParPRT* PosParPRT::_free_list = NULL;
ysr@777 483 PosParPRT* PosParPRT::_par_expanded_list = NULL;
ysr@777 484
ysr@777 485 jint OtherRegionsTable::_cache_probes = 0;
ysr@777 486 jint OtherRegionsTable::_cache_hits = 0;
ysr@777 487
ysr@777 488 size_t OtherRegionsTable::_max_fine_entries = 0;
ysr@777 489 size_t OtherRegionsTable::_mod_max_fine_entries_mask = 0;
ysr@777 490 #if SAMPLE_FOR_EVICTION
ysr@777 491 size_t OtherRegionsTable::_fine_eviction_stride = 0;
ysr@777 492 size_t OtherRegionsTable::_fine_eviction_sample_size = 0;
ysr@777 493 #endif
ysr@777 494
ysr@777 495 OtherRegionsTable::OtherRegionsTable(HeapRegion* hr) :
ysr@777 496 _g1h(G1CollectedHeap::heap()),
ysr@777 497 _m(Mutex::leaf, "An OtherRegionsTable lock", true),
ysr@777 498 _hr(hr),
ysr@777 499 _coarse_map(G1CollectedHeap::heap()->max_regions(),
ysr@777 500 false /* in-resource-area */),
ysr@777 501 _fine_grain_regions(NULL),
ysr@777 502 _n_fine_entries(0), _n_coarse_entries(0),
ysr@777 503 #if SAMPLE_FOR_EVICTION
ysr@777 504 _fine_eviction_start(0),
ysr@777 505 #endif
ysr@777 506 _sparse_table(hr)
ysr@777 507 {
ysr@777 508 typedef PosParPRT* PosParPRTPtr;
ysr@777 509 if (_max_fine_entries == 0) {
ysr@777 510 assert(_mod_max_fine_entries_mask == 0, "Both or none.");
kvn@1080 511 _max_fine_entries = (size_t)(1 << G1LogRSRegionEntries);
ysr@777 512 _mod_max_fine_entries_mask = _max_fine_entries - 1;
ysr@777 513 #if SAMPLE_FOR_EVICTION
ysr@777 514 assert(_fine_eviction_sample_size == 0
ysr@777 515 && _fine_eviction_stride == 0, "All init at same time.");
ysr@777 516 _fine_eviction_sample_size = MAX2((size_t)4, (size_t)G1LogRSRegionEntries);
ysr@777 517 _fine_eviction_stride = _max_fine_entries / _fine_eviction_sample_size;
ysr@777 518 #endif
ysr@777 519 }
ysr@777 520 _fine_grain_regions = new PosParPRTPtr[_max_fine_entries];
ysr@777 521 if (_fine_grain_regions == NULL)
ysr@777 522 vm_exit_out_of_memory(sizeof(void*)*_max_fine_entries,
ysr@777 523 "Failed to allocate _fine_grain_entries.");
ysr@777 524 for (size_t i = 0; i < _max_fine_entries; i++) {
ysr@777 525 _fine_grain_regions[i] = NULL;
ysr@777 526 }
ysr@777 527 }
ysr@777 528
ysr@777 529 int** OtherRegionsTable::_from_card_cache = NULL;
ysr@777 530 size_t OtherRegionsTable::_from_card_cache_max_regions = 0;
ysr@777 531 size_t OtherRegionsTable::_from_card_cache_mem_size = 0;
ysr@777 532
ysr@777 533 void OtherRegionsTable::init_from_card_cache(size_t max_regions) {
ysr@777 534 _from_card_cache_max_regions = max_regions;
ysr@777 535
ysr@777 536 int n_par_rs = HeapRegionRemSet::num_par_rem_sets();
ysr@777 537 _from_card_cache = NEW_C_HEAP_ARRAY(int*, n_par_rs);
ysr@777 538 for (int i = 0; i < n_par_rs; i++) {
ysr@777 539 _from_card_cache[i] = NEW_C_HEAP_ARRAY(int, max_regions);
ysr@777 540 for (size_t j = 0; j < max_regions; j++) {
ysr@777 541 _from_card_cache[i][j] = -1; // An invalid value.
ysr@777 542 }
ysr@777 543 }
ysr@777 544 _from_card_cache_mem_size = n_par_rs * max_regions * sizeof(int);
ysr@777 545 }
ysr@777 546
ysr@777 547 void OtherRegionsTable::shrink_from_card_cache(size_t new_n_regs) {
ysr@777 548 for (int i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) {
ysr@777 549 assert(new_n_regs <= _from_card_cache_max_regions, "Must be within max.");
ysr@777 550 for (size_t j = new_n_regs; j < _from_card_cache_max_regions; j++) {
ysr@777 551 _from_card_cache[i][j] = -1; // An invalid value.
ysr@777 552 }
ysr@777 553 }
ysr@777 554 }
ysr@777 555
ysr@777 556 #ifndef PRODUCT
ysr@777 557 void OtherRegionsTable::print_from_card_cache() {
ysr@777 558 for (int i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) {
ysr@777 559 for (size_t j = 0; j < _from_card_cache_max_regions; j++) {
ysr@777 560 gclog_or_tty->print_cr("_from_card_cache[%d][%d] = %d.",
ysr@777 561 i, j, _from_card_cache[i][j]);
ysr@777 562 }
ysr@777 563 }
ysr@777 564 }
ysr@777 565 #endif
ysr@777 566
ysr@1280 567 void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, int tid) {
ysr@777 568 size_t cur_hrs_ind = hr()->hrs_index();
ysr@777 569
ysr@777 570 #if HRRS_VERBOSE
ysr@777 571 gclog_or_tty->print_cr("ORT::add_reference_work(" PTR_FORMAT "->" PTR_FORMAT ").",
ysr@1280 572 from,
ysr@1280 573 UseCompressedOops
ysr@1280 574 ? oopDesc::load_decode_heap_oop((narrowOop*)from)
ysr@1280 575 : oopDesc::load_decode_heap_oop((oop*)from));
ysr@777 576 #endif
ysr@777 577
ysr@777 578 int from_card = (int)(uintptr_t(from) >> CardTableModRefBS::card_shift);
ysr@777 579
ysr@777 580 #if HRRS_VERBOSE
ysr@777 581 gclog_or_tty->print_cr("Table for [" PTR_FORMAT "...): card %d (cache = %d)",
ysr@777 582 hr()->bottom(), from_card,
ysr@777 583 _from_card_cache[tid][cur_hrs_ind]);
ysr@777 584 #endif
ysr@777 585
ysr@777 586 #define COUNT_CACHE 0
ysr@777 587 #if COUNT_CACHE
ysr@777 588 jint p = Atomic::add(1, &_cache_probes);
ysr@777 589 if ((p % 10000) == 0) {
ysr@777 590 jint hits = _cache_hits;
ysr@777 591 gclog_or_tty->print_cr("%d/%d = %5.2f%% RS cache hits.",
ysr@777 592 _cache_hits, p, 100.0* (float)hits/(float)p);
ysr@777 593 }
ysr@777 594 #endif
ysr@777 595 if (from_card == _from_card_cache[tid][cur_hrs_ind]) {
ysr@777 596 #if HRRS_VERBOSE
ysr@777 597 gclog_or_tty->print_cr(" from-card cache hit.");
ysr@777 598 #endif
ysr@777 599 #if COUNT_CACHE
ysr@777 600 Atomic::inc(&_cache_hits);
ysr@777 601 #endif
ysr@777 602 assert(contains_reference(from), "We just added it!");
ysr@777 603 return;
ysr@777 604 } else {
ysr@777 605 _from_card_cache[tid][cur_hrs_ind] = from_card;
ysr@777 606 }
ysr@777 607
ysr@777 608 // Note that this may be a continued H region.
ysr@777 609 HeapRegion* from_hr = _g1h->heap_region_containing_raw(from);
johnc@1242 610 RegionIdx_t from_hrs_ind = (RegionIdx_t) from_hr->hrs_index();
ysr@777 611
ysr@777 612 // If the region is already coarsened, return.
ysr@777 613 if (_coarse_map.at(from_hrs_ind)) {
ysr@777 614 #if HRRS_VERBOSE
ysr@777 615 gclog_or_tty->print_cr(" coarse map hit.");
ysr@777 616 #endif
ysr@777 617 assert(contains_reference(from), "We just added it!");
ysr@777 618 return;
ysr@777 619 }
ysr@777 620
ysr@777 621 // Otherwise find a per-region table to add it to.
ysr@777 622 size_t ind = from_hrs_ind & _mod_max_fine_entries_mask;
ysr@777 623 PosParPRT* prt = find_region_table(ind, from_hr);
ysr@777 624 if (prt == NULL) {
ysr@777 625 MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
ysr@777 626 // Confirm that it's really not there...
ysr@777 627 prt = find_region_table(ind, from_hr);
ysr@777 628 if (prt == NULL) {
ysr@777 629
ysr@777 630 uintptr_t from_hr_bot_card_index =
ysr@777 631 uintptr_t(from_hr->bottom())
ysr@777 632 >> CardTableModRefBS::card_shift;
johnc@1242 633 CardIdx_t card_index = from_card - from_hr_bot_card_index;
ysr@777 634 assert(0 <= card_index && card_index < PosParPRT::CardsPerRegion,
ysr@777 635 "Must be in range.");
ysr@777 636 if (G1HRRSUseSparseTable &&
johnc@1242 637 _sparse_table.add_card(from_hrs_ind, card_index)) {
ysr@777 638 if (G1RecordHRRSOops) {
ysr@777 639 HeapRegionRemSet::record(hr(), from);
ysr@777 640 #if HRRS_VERBOSE
ysr@777 641 gclog_or_tty->print(" Added card " PTR_FORMAT " to region "
ysr@777 642 "[" PTR_FORMAT "...) for ref " PTR_FORMAT ".\n",
ysr@777 643 align_size_down(uintptr_t(from),
ysr@777 644 CardTableModRefBS::card_size),
ysr@777 645 hr()->bottom(), from);
ysr@777 646 #endif
ysr@777 647 }
ysr@777 648 #if HRRS_VERBOSE
ysr@777 649 gclog_or_tty->print_cr(" added card to sparse table.");
ysr@777 650 #endif
ysr@777 651 assert(contains_reference_locked(from), "We just added it!");
ysr@777 652 return;
ysr@777 653 } else {
ysr@777 654 #if HRRS_VERBOSE
ysr@777 655 gclog_or_tty->print_cr(" [tid %d] sparse table entry "
ysr@777 656 "overflow(f: %d, t: %d)",
ysr@777 657 tid, from_hrs_ind, cur_hrs_ind);
ysr@777 658 #endif
ysr@777 659 }
ysr@777 660
ysr@777 661 // Otherwise, transfer from sparse to fine-grain.
johnc@1242 662 CardIdx_t cards[SparsePRTEntry::CardsPerEntry];
ysr@777 663 if (G1HRRSUseSparseTable) {
johnc@1242 664 bool res = _sparse_table.get_cards(from_hrs_ind, &cards[0]);
ysr@777 665 assert(res, "There should have been an entry");
ysr@777 666 }
ysr@777 667
ysr@777 668 if (_n_fine_entries == _max_fine_entries) {
ysr@777 669 prt = delete_region_table();
ysr@777 670 } else {
ysr@777 671 prt = PosParPRT::alloc(from_hr);
ysr@777 672 }
ysr@777 673 prt->init(from_hr);
ysr@777 674 // Record the outgoing pointer in the from_region's outgoing bitmap.
ysr@777 675 from_hr->rem_set()->add_outgoing_reference(hr());
ysr@777 676
ysr@777 677 PosParPRT* first_prt = _fine_grain_regions[ind];
ysr@777 678 prt->set_next(first_prt); // XXX Maybe move to init?
ysr@777 679 _fine_grain_regions[ind] = prt;
ysr@777 680 _n_fine_entries++;
ysr@777 681
ysr@777 682 // Add in the cards from the sparse table.
ysr@777 683 if (G1HRRSUseSparseTable) {
ysr@777 684 for (int i = 0; i < SparsePRTEntry::CardsPerEntry; i++) {
johnc@1242 685 CardIdx_t c = cards[i];
ysr@777 686 if (c != SparsePRTEntry::NullEntry) {
ysr@777 687 prt->add_card(c);
ysr@777 688 }
ysr@777 689 }
ysr@777 690 // Now we can delete the sparse entry.
johnc@1242 691 bool res = _sparse_table.delete_entry(from_hrs_ind);
ysr@777 692 assert(res, "It should have been there.");
ysr@777 693 }
ysr@777 694 }
ysr@777 695 assert(prt != NULL && prt->hr() == from_hr, "consequence");
ysr@777 696 }
ysr@777 697 // Note that we can't assert "prt->hr() == from_hr", because of the
ysr@777 698 // possibility of concurrent reuse. But see head comment of
ysr@777 699 // OtherRegionsTable for why this is OK.
ysr@777 700 assert(prt != NULL, "Inv");
ysr@777 701
ysr@777 702 prt->add_reference(from, tid);
ysr@777 703 if (G1RecordHRRSOops) {
ysr@777 704 HeapRegionRemSet::record(hr(), from);
ysr@777 705 #if HRRS_VERBOSE
ysr@777 706 gclog_or_tty->print("Added card " PTR_FORMAT " to region "
ysr@777 707 "[" PTR_FORMAT "...) for ref " PTR_FORMAT ".\n",
ysr@777 708 align_size_down(uintptr_t(from),
ysr@777 709 CardTableModRefBS::card_size),
ysr@777 710 hr()->bottom(), from);
ysr@777 711 #endif
ysr@777 712 }
ysr@777 713 assert(contains_reference(from), "We just added it!");
ysr@777 714 }
ysr@777 715
ysr@777 716 PosParPRT*
ysr@777 717 OtherRegionsTable::find_region_table(size_t ind, HeapRegion* hr) const {
ysr@777 718 assert(0 <= ind && ind < _max_fine_entries, "Preconditions.");
ysr@777 719 PosParPRT* prt = _fine_grain_regions[ind];
ysr@777 720 while (prt != NULL && prt->hr() != hr) {
ysr@777 721 prt = prt->next();
ysr@777 722 }
ysr@777 723 // Loop postcondition is the method postcondition.
ysr@777 724 return prt;
ysr@777 725 }
ysr@777 726
ysr@777 727
ysr@777 728 #define DRT_CENSUS 0
ysr@777 729
ysr@777 730 #if DRT_CENSUS
ysr@777 731 static const int HistoSize = 6;
ysr@777 732 static int global_histo[HistoSize] = { 0, 0, 0, 0, 0, 0 };
ysr@777 733 static int coarsenings = 0;
ysr@777 734 static int occ_sum = 0;
ysr@777 735 #endif
ysr@777 736
ysr@777 737 jint OtherRegionsTable::_n_coarsenings = 0;
ysr@777 738
ysr@777 739 PosParPRT* OtherRegionsTable::delete_region_table() {
ysr@777 740 #if DRT_CENSUS
ysr@777 741 int histo[HistoSize] = { 0, 0, 0, 0, 0, 0 };
ysr@777 742 const int histo_limits[] = { 1, 4, 16, 64, 256, 2048 };
ysr@777 743 #endif
ysr@777 744
ysr@777 745 assert(_m.owned_by_self(), "Precondition");
ysr@777 746 assert(_n_fine_entries == _max_fine_entries, "Precondition");
ysr@777 747 PosParPRT* max = NULL;
ysr@777 748 jint max_occ = 0;
ysr@777 749 PosParPRT** max_prev;
ysr@777 750 size_t max_ind;
ysr@777 751
ysr@777 752 #if SAMPLE_FOR_EVICTION
ysr@777 753 size_t i = _fine_eviction_start;
ysr@777 754 for (size_t k = 0; k < _fine_eviction_sample_size; k++) {
ysr@777 755 size_t ii = i;
ysr@777 756 // Make sure we get a non-NULL sample.
ysr@777 757 while (_fine_grain_regions[ii] == NULL) {
ysr@777 758 ii++;
ysr@777 759 if (ii == _max_fine_entries) ii = 0;
ysr@777 760 guarantee(ii != i, "We must find one.");
ysr@777 761 }
ysr@777 762 PosParPRT** prev = &_fine_grain_regions[ii];
ysr@777 763 PosParPRT* cur = *prev;
ysr@777 764 while (cur != NULL) {
ysr@777 765 jint cur_occ = cur->occupied();
ysr@777 766 if (max == NULL || cur_occ > max_occ) {
ysr@777 767 max = cur;
ysr@777 768 max_prev = prev;
ysr@777 769 max_ind = i;
ysr@777 770 max_occ = cur_occ;
ysr@777 771 }
ysr@777 772 prev = cur->next_addr();
ysr@777 773 cur = cur->next();
ysr@777 774 }
ysr@777 775 i = i + _fine_eviction_stride;
ysr@777 776 if (i >= _n_fine_entries) i = i - _n_fine_entries;
ysr@777 777 }
ysr@777 778 _fine_eviction_start++;
ysr@777 779 if (_fine_eviction_start >= _n_fine_entries)
ysr@777 780 _fine_eviction_start -= _n_fine_entries;
ysr@777 781 #else
ysr@777 782 for (int i = 0; i < _max_fine_entries; i++) {
ysr@777 783 PosParPRT** prev = &_fine_grain_regions[i];
ysr@777 784 PosParPRT* cur = *prev;
ysr@777 785 while (cur != NULL) {
ysr@777 786 jint cur_occ = cur->occupied();
ysr@777 787 #if DRT_CENSUS
ysr@777 788 for (int k = 0; k < HistoSize; k++) {
ysr@777 789 if (cur_occ <= histo_limits[k]) {
ysr@777 790 histo[k]++; global_histo[k]++; break;
ysr@777 791 }
ysr@777 792 }
ysr@777 793 #endif
ysr@777 794 if (max == NULL || cur_occ > max_occ) {
ysr@777 795 max = cur;
ysr@777 796 max_prev = prev;
ysr@777 797 max_ind = i;
ysr@777 798 max_occ = cur_occ;
ysr@777 799 }
ysr@777 800 prev = cur->next_addr();
ysr@777 801 cur = cur->next();
ysr@777 802 }
ysr@777 803 }
ysr@777 804 #endif
ysr@777 805 // XXX
ysr@777 806 guarantee(max != NULL, "Since _n_fine_entries > 0");
ysr@777 807 #if DRT_CENSUS
ysr@777 808 gclog_or_tty->print_cr("In a coarsening: histo of occs:");
ysr@777 809 for (int k = 0; k < HistoSize; k++) {
ysr@777 810 gclog_or_tty->print_cr(" <= %4d: %5d.", histo_limits[k], histo[k]);
ysr@777 811 }
ysr@777 812 coarsenings++;
ysr@777 813 occ_sum += max_occ;
ysr@777 814 if ((coarsenings % 100) == 0) {
ysr@777 815 gclog_or_tty->print_cr("\ncoarsenings = %d; global summary:", coarsenings);
ysr@777 816 for (int k = 0; k < HistoSize; k++) {
ysr@777 817 gclog_or_tty->print_cr(" <= %4d: %5d.", histo_limits[k], global_histo[k]);
ysr@777 818 }
ysr@777 819 gclog_or_tty->print_cr("Avg occ of deleted region = %6.2f.",
ysr@777 820 (float)occ_sum/(float)coarsenings);
ysr@777 821 }
ysr@777 822 #endif
ysr@777 823
ysr@777 824 // Set the corresponding coarse bit.
ysr@777 825 int max_hrs_index = max->hr()->hrs_index();
ysr@777 826 if (!_coarse_map.at(max_hrs_index)) {
ysr@777 827 _coarse_map.at_put(max_hrs_index, true);
ysr@777 828 _n_coarse_entries++;
ysr@777 829 #if 0
ysr@777 830 gclog_or_tty->print("Coarsened entry in region [" PTR_FORMAT "...] "
ysr@777 831 "for region [" PTR_FORMAT "...] (%d coarse entries).\n",
ysr@777 832 hr()->bottom(),
ysr@777 833 max->hr()->bottom(),
ysr@777 834 _n_coarse_entries);
ysr@777 835 #endif
ysr@777 836 }
ysr@777 837
ysr@777 838 // Unsplice.
ysr@777 839 *max_prev = max->next();
ysr@777 840 Atomic::inc(&_n_coarsenings);
ysr@777 841 _n_fine_entries--;
ysr@777 842 return max;
ysr@777 843 }
ysr@777 844
ysr@777 845
ysr@777 846 // At present, this must be called stop-world single-threaded.
ysr@777 847 void OtherRegionsTable::scrub(CardTableModRefBS* ctbs,
ysr@777 848 BitMap* region_bm, BitMap* card_bm) {
ysr@777 849 // First eliminated garbage regions from the coarse map.
ysr@777 850 if (G1RSScrubVerbose)
ysr@777 851 gclog_or_tty->print_cr("Scrubbing region %d:", hr()->hrs_index());
ysr@777 852
ysr@777 853 assert(_coarse_map.size() == region_bm->size(), "Precondition");
ysr@777 854 if (G1RSScrubVerbose)
ysr@777 855 gclog_or_tty->print(" Coarse map: before = %d...", _n_coarse_entries);
ysr@777 856 _coarse_map.set_intersection(*region_bm);
ysr@777 857 _n_coarse_entries = _coarse_map.count_one_bits();
ysr@777 858 if (G1RSScrubVerbose)
ysr@777 859 gclog_or_tty->print_cr(" after = %d.", _n_coarse_entries);
ysr@777 860
ysr@777 861 // Now do the fine-grained maps.
ysr@777 862 for (size_t i = 0; i < _max_fine_entries; i++) {
ysr@777 863 PosParPRT* cur = _fine_grain_regions[i];
ysr@777 864 PosParPRT** prev = &_fine_grain_regions[i];
ysr@777 865 while (cur != NULL) {
ysr@777 866 PosParPRT* nxt = cur->next();
ysr@777 867 // If the entire region is dead, eliminate.
ysr@777 868 if (G1RSScrubVerbose)
ysr@777 869 gclog_or_tty->print_cr(" For other region %d:", cur->hr()->hrs_index());
ysr@777 870 if (!region_bm->at(cur->hr()->hrs_index())) {
ysr@777 871 *prev = nxt;
ysr@777 872 cur->set_next(NULL);
ysr@777 873 _n_fine_entries--;
ysr@777 874 if (G1RSScrubVerbose)
ysr@777 875 gclog_or_tty->print_cr(" deleted via region map.");
ysr@777 876 PosParPRT::free(cur);
ysr@777 877 } else {
ysr@777 878 // Do fine-grain elimination.
ysr@777 879 if (G1RSScrubVerbose)
ysr@777 880 gclog_or_tty->print(" occ: before = %4d.", cur->occupied());
ysr@777 881 cur->scrub(ctbs, card_bm);
ysr@777 882 if (G1RSScrubVerbose)
ysr@777 883 gclog_or_tty->print_cr(" after = %4d.", cur->occupied());
ysr@777 884 // Did that empty the table completely?
ysr@777 885 if (cur->occupied() == 0) {
ysr@777 886 *prev = nxt;
ysr@777 887 cur->set_next(NULL);
ysr@777 888 _n_fine_entries--;
ysr@777 889 PosParPRT::free(cur);
ysr@777 890 } else {
ysr@777 891 prev = cur->next_addr();
ysr@777 892 }
ysr@777 893 }
ysr@777 894 cur = nxt;
ysr@777 895 }
ysr@777 896 }
ysr@777 897 // Since we may have deleted a from_card_cache entry from the RS, clear
ysr@777 898 // the FCC.
ysr@777 899 clear_fcc();
ysr@777 900 }
ysr@777 901
ysr@777 902
ysr@777 903 size_t OtherRegionsTable::occupied() const {
ysr@777 904 // Cast away const in this case.
ysr@777 905 MutexLockerEx x((Mutex*)&_m, Mutex::_no_safepoint_check_flag);
ysr@777 906 size_t sum = occ_fine();
ysr@777 907 sum += occ_sparse();
ysr@777 908 sum += occ_coarse();
ysr@777 909 return sum;
ysr@777 910 }
ysr@777 911
ysr@777 912 size_t OtherRegionsTable::occ_fine() const {
ysr@777 913 size_t sum = 0;
ysr@777 914 for (size_t i = 0; i < _max_fine_entries; i++) {
ysr@777 915 PosParPRT* cur = _fine_grain_regions[i];
ysr@777 916 while (cur != NULL) {
ysr@777 917 sum += cur->occupied();
ysr@777 918 cur = cur->next();
ysr@777 919 }
ysr@777 920 }
ysr@777 921 return sum;
ysr@777 922 }
ysr@777 923
ysr@777 924 size_t OtherRegionsTable::occ_coarse() const {
ysr@777 925 return (_n_coarse_entries * PosParPRT::CardsPerRegion);
ysr@777 926 }
ysr@777 927
ysr@777 928 size_t OtherRegionsTable::occ_sparse() const {
ysr@777 929 return _sparse_table.occupied();
ysr@777 930 }
ysr@777 931
ysr@777 932 size_t OtherRegionsTable::mem_size() const {
ysr@777 933 // Cast away const in this case.
ysr@777 934 MutexLockerEx x((Mutex*)&_m, Mutex::_no_safepoint_check_flag);
ysr@777 935 size_t sum = 0;
ysr@777 936 for (size_t i = 0; i < _max_fine_entries; i++) {
ysr@777 937 PosParPRT* cur = _fine_grain_regions[i];
ysr@777 938 while (cur != NULL) {
ysr@777 939 sum += cur->mem_size();
ysr@777 940 cur = cur->next();
ysr@777 941 }
ysr@777 942 }
ysr@777 943 sum += (sizeof(PosParPRT*) * _max_fine_entries);
ysr@777 944 sum += (_coarse_map.size_in_words() * HeapWordSize);
ysr@777 945 sum += (_sparse_table.mem_size());
ysr@777 946 sum += sizeof(*this) - sizeof(_sparse_table); // Avoid double counting above.
ysr@777 947 return sum;
ysr@777 948 }
ysr@777 949
ysr@777 950 size_t OtherRegionsTable::static_mem_size() {
ysr@777 951 return _from_card_cache_mem_size;
ysr@777 952 }
ysr@777 953
ysr@777 954 size_t OtherRegionsTable::fl_mem_size() {
ysr@777 955 return PerRegionTable::fl_mem_size() + PosParPRT::fl_mem_size();
ysr@777 956 }
ysr@777 957
ysr@777 958 void OtherRegionsTable::clear_fcc() {
ysr@777 959 for (int i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) {
ysr@777 960 _from_card_cache[i][hr()->hrs_index()] = -1;
ysr@777 961 }
ysr@777 962 }
ysr@777 963
ysr@777 964 void OtherRegionsTable::clear() {
ysr@777 965 MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
ysr@777 966 for (size_t i = 0; i < _max_fine_entries; i++) {
ysr@777 967 PosParPRT* cur = _fine_grain_regions[i];
ysr@777 968 while (cur != NULL) {
ysr@777 969 PosParPRT* nxt = cur->next();
ysr@777 970 PosParPRT::free(cur);
ysr@777 971 cur = nxt;
ysr@777 972 }
ysr@777 973 _fine_grain_regions[i] = NULL;
ysr@777 974 }
ysr@777 975 _sparse_table.clear();
ysr@777 976 _coarse_map.clear();
ysr@777 977 _n_fine_entries = 0;
ysr@777 978 _n_coarse_entries = 0;
ysr@777 979
ysr@777 980 clear_fcc();
ysr@777 981 }
ysr@777 982
ysr@777 983 void OtherRegionsTable::clear_incoming_entry(HeapRegion* from_hr) {
ysr@777 984 MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
ysr@777 985 size_t hrs_ind = (size_t)from_hr->hrs_index();
ysr@777 986 size_t ind = hrs_ind & _mod_max_fine_entries_mask;
ysr@777 987 if (del_single_region_table(ind, from_hr)) {
ysr@777 988 assert(!_coarse_map.at(hrs_ind), "Inv");
ysr@777 989 } else {
ysr@777 990 _coarse_map.par_at_put(hrs_ind, 0);
ysr@777 991 }
ysr@777 992 // Check to see if any of the fcc entries come from here.
ysr@777 993 int hr_ind = hr()->hrs_index();
ysr@777 994 for (int tid = 0; tid < HeapRegionRemSet::num_par_rem_sets(); tid++) {
ysr@777 995 int fcc_ent = _from_card_cache[tid][hr_ind];
ysr@777 996 if (fcc_ent != -1) {
ysr@777 997 HeapWord* card_addr = (HeapWord*)
ysr@777 998 (uintptr_t(fcc_ent) << CardTableModRefBS::card_shift);
ysr@777 999 if (hr()->is_in_reserved(card_addr)) {
ysr@777 1000 // Clear the from card cache.
ysr@777 1001 _from_card_cache[tid][hr_ind] = -1;
ysr@777 1002 }
ysr@777 1003 }
ysr@777 1004 }
ysr@777 1005 }
ysr@777 1006
ysr@777 1007 bool OtherRegionsTable::del_single_region_table(size_t ind,
ysr@777 1008 HeapRegion* hr) {
ysr@777 1009 assert(0 <= ind && ind < _max_fine_entries, "Preconditions.");
ysr@777 1010 PosParPRT** prev_addr = &_fine_grain_regions[ind];
ysr@777 1011 PosParPRT* prt = *prev_addr;
ysr@777 1012 while (prt != NULL && prt->hr() != hr) {
ysr@777 1013 prev_addr = prt->next_addr();
ysr@777 1014 prt = prt->next();
ysr@777 1015 }
ysr@777 1016 if (prt != NULL) {
ysr@777 1017 assert(prt->hr() == hr, "Loop postcondition.");
ysr@777 1018 *prev_addr = prt->next();
ysr@777 1019 PosParPRT::free(prt);
ysr@777 1020 _n_fine_entries--;
ysr@777 1021 return true;
ysr@777 1022 } else {
ysr@777 1023 return false;
ysr@777 1024 }
ysr@777 1025 }
ysr@777 1026
ysr@1280 1027 bool OtherRegionsTable::contains_reference(OopOrNarrowOopStar from) const {
ysr@777 1028 // Cast away const in this case.
ysr@777 1029 MutexLockerEx x((Mutex*)&_m, Mutex::_no_safepoint_check_flag);
ysr@777 1030 return contains_reference_locked(from);
ysr@777 1031 }
ysr@777 1032
ysr@1280 1033 bool OtherRegionsTable::contains_reference_locked(OopOrNarrowOopStar from) const {
ysr@777 1034 HeapRegion* hr = _g1h->heap_region_containing_raw(from);
ysr@777 1035 if (hr == NULL) return false;
johnc@1242 1036 RegionIdx_t hr_ind = (RegionIdx_t) hr->hrs_index();
ysr@777 1037 // Is this region in the coarse map?
ysr@777 1038 if (_coarse_map.at(hr_ind)) return true;
ysr@777 1039
ysr@777 1040 PosParPRT* prt = find_region_table(hr_ind & _mod_max_fine_entries_mask,
ysr@777 1041 hr);
ysr@777 1042 if (prt != NULL) {
ysr@777 1043 return prt->contains_reference(from);
ysr@777 1044
ysr@777 1045 } else {
ysr@777 1046 uintptr_t from_card =
ysr@777 1047 (uintptr_t(from) >> CardTableModRefBS::card_shift);
ysr@777 1048 uintptr_t hr_bot_card_index =
ysr@777 1049 uintptr_t(hr->bottom()) >> CardTableModRefBS::card_shift;
ysr@777 1050 assert(from_card >= hr_bot_card_index, "Inv");
johnc@1242 1051 CardIdx_t card_index = from_card - hr_bot_card_index;
johnc@1242 1052 assert(0 <= card_index && card_index < PosParPRT::CardsPerRegion, "Must be in range.");
johnc@1242 1053 return _sparse_table.contains_card(hr_ind, card_index);
ysr@777 1054 }
ysr@777 1055
ysr@777 1056
ysr@777 1057 }
ysr@777 1058
iveresov@1230 1059 // Determines how many threads can add records to an rset in parallel.
iveresov@1230 1060 // This can be done by either mutator threads together with the
iveresov@1230 1061 // concurrent refinement threads or GC threads.
ysr@777 1062 int HeapRegionRemSet::num_par_rem_sets() {
iveresov@1230 1063 return (int)MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), ParallelGCThreads);
ysr@777 1064 }
ysr@777 1065
ysr@777 1066 HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa,
ysr@777 1067 HeapRegion* hr)
ysr@777 1068 : _bosa(bosa), _other_regions(hr),
ysr@777 1069 _outgoing_region_map(G1CollectedHeap::heap()->max_regions(),
ysr@777 1070 false /* in-resource-area */),
ysr@777 1071 _iter_state(Unclaimed)
ysr@777 1072 {}
ysr@777 1073
ysr@777 1074
ysr@777 1075 void HeapRegionRemSet::init_for_par_iteration() {
ysr@777 1076 _iter_state = Unclaimed;
ysr@777 1077 }
ysr@777 1078
ysr@777 1079 bool HeapRegionRemSet::claim_iter() {
ysr@777 1080 if (_iter_state != Unclaimed) return false;
ysr@777 1081 jint res = Atomic::cmpxchg(Claimed, (jint*)(&_iter_state), Unclaimed);
ysr@777 1082 return (res == Unclaimed);
ysr@777 1083 }
ysr@777 1084
ysr@777 1085 void HeapRegionRemSet::set_iter_complete() {
ysr@777 1086 _iter_state = Complete;
ysr@777 1087 }
ysr@777 1088
ysr@777 1089 bool HeapRegionRemSet::iter_is_complete() {
ysr@777 1090 return _iter_state == Complete;
ysr@777 1091 }
ysr@777 1092
ysr@777 1093
ysr@777 1094 void HeapRegionRemSet::init_iterator(HeapRegionRemSetIterator* iter) const {
ysr@777 1095 iter->initialize(this);
ysr@777 1096 }
ysr@777 1097
ysr@777 1098 #ifndef PRODUCT
ysr@777 1099 void HeapRegionRemSet::print() const {
ysr@777 1100 HeapRegionRemSetIterator iter;
ysr@777 1101 init_iterator(&iter);
ysr@777 1102 size_t card_index;
ysr@777 1103 while (iter.has_next(card_index)) {
ysr@777 1104 HeapWord* card_start =
ysr@777 1105 G1CollectedHeap::heap()->bot_shared()->address_for_index(card_index);
ysr@777 1106 gclog_or_tty->print_cr(" Card " PTR_FORMAT ".", card_start);
ysr@777 1107 }
ysr@777 1108 // XXX
ysr@777 1109 if (iter.n_yielded() != occupied()) {
ysr@777 1110 gclog_or_tty->print_cr("Yielded disagrees with occupied:");
ysr@777 1111 gclog_or_tty->print_cr(" %6d yielded (%6d coarse, %6d fine).",
ysr@777 1112 iter.n_yielded(),
ysr@777 1113 iter.n_yielded_coarse(), iter.n_yielded_fine());
ysr@777 1114 gclog_or_tty->print_cr(" %6d occ (%6d coarse, %6d fine).",
ysr@777 1115 occupied(), occ_coarse(), occ_fine());
ysr@777 1116 }
ysr@777 1117 guarantee(iter.n_yielded() == occupied(),
ysr@777 1118 "We should have yielded all the represented cards.");
ysr@777 1119 }
ysr@777 1120 #endif
ysr@777 1121
ysr@777 1122 void HeapRegionRemSet::cleanup() {
ysr@777 1123 SparsePRT::cleanup_all();
ysr@777 1124 }
ysr@777 1125
ysr@777 1126 void HeapRegionRemSet::par_cleanup() {
ysr@777 1127 PosParPRT::par_contract_all();
ysr@777 1128 }
ysr@777 1129
ysr@777 1130 void HeapRegionRemSet::add_outgoing_reference(HeapRegion* to_hr) {
ysr@777 1131 _outgoing_region_map.par_at_put(to_hr->hrs_index(), 1);
ysr@777 1132 }
ysr@777 1133
ysr@777 1134 void HeapRegionRemSet::clear() {
ysr@777 1135 clear_outgoing_entries();
ysr@777 1136 _outgoing_region_map.clear();
ysr@777 1137 _other_regions.clear();
ysr@777 1138 assert(occupied() == 0, "Should be clear.");
ysr@777 1139 }
ysr@777 1140
ysr@777 1141 void HeapRegionRemSet::clear_outgoing_entries() {
ysr@777 1142 G1CollectedHeap* g1h = G1CollectedHeap::heap();
ysr@777 1143 size_t i = _outgoing_region_map.get_next_one_offset(0);
ysr@777 1144 while (i < _outgoing_region_map.size()) {
ysr@777 1145 HeapRegion* to_region = g1h->region_at(i);
apetrusenko@980 1146 if (!to_region->in_collection_set()) {
apetrusenko@980 1147 to_region->rem_set()->clear_incoming_entry(hr());
apetrusenko@980 1148 }
ysr@777 1149 i = _outgoing_region_map.get_next_one_offset(i+1);
ysr@777 1150 }
ysr@777 1151 }
ysr@777 1152
ysr@777 1153
ysr@777 1154 void HeapRegionRemSet::scrub(CardTableModRefBS* ctbs,
ysr@777 1155 BitMap* region_bm, BitMap* card_bm) {
ysr@777 1156 _other_regions.scrub(ctbs, region_bm, card_bm);
ysr@777 1157 }
ysr@777 1158
ysr@777 1159 //-------------------- Iteration --------------------
ysr@777 1160
ysr@777 1161 HeapRegionRemSetIterator::
ysr@777 1162 HeapRegionRemSetIterator() :
ysr@777 1163 _hrrs(NULL),
ysr@777 1164 _g1h(G1CollectedHeap::heap()),
ysr@777 1165 _bosa(NULL),
ysr@777 1166 _sparse_iter(size_t(G1CollectedHeap::heap()->reserved_region().start())
ysr@777 1167 >> CardTableModRefBS::card_shift)
ysr@777 1168 {}
ysr@777 1169
ysr@777 1170 void HeapRegionRemSetIterator::initialize(const HeapRegionRemSet* hrrs) {
ysr@777 1171 _hrrs = hrrs;
ysr@777 1172 _coarse_map = &_hrrs->_other_regions._coarse_map;
ysr@777 1173 _fine_grain_regions = _hrrs->_other_regions._fine_grain_regions;
ysr@777 1174 _bosa = _hrrs->bosa();
ysr@777 1175
ysr@777 1176 _is = Sparse;
ysr@777 1177 // Set these values so that we increment to the first region.
ysr@777 1178 _coarse_cur_region_index = -1;
ysr@777 1179 _coarse_cur_region_cur_card = (PosParPRT::CardsPerRegion-1);;
ysr@777 1180
ysr@777 1181 _cur_region_cur_card = 0;
ysr@777 1182
ysr@777 1183 _fine_array_index = -1;
ysr@777 1184 _fine_cur_prt = NULL;
ysr@777 1185
ysr@777 1186 _n_yielded_coarse = 0;
ysr@777 1187 _n_yielded_fine = 0;
ysr@777 1188 _n_yielded_sparse = 0;
ysr@777 1189
ysr@777 1190 _sparse_iter.init(&hrrs->_other_regions._sparse_table);
ysr@777 1191 }
ysr@777 1192
ysr@777 1193 bool HeapRegionRemSetIterator::coarse_has_next(size_t& card_index) {
ysr@777 1194 if (_hrrs->_other_regions._n_coarse_entries == 0) return false;
ysr@777 1195 // Go to the next card.
ysr@777 1196 _coarse_cur_region_cur_card++;
ysr@777 1197 // Was the last the last card in the current region?
ysr@777 1198 if (_coarse_cur_region_cur_card == PosParPRT::CardsPerRegion) {
ysr@777 1199 // Yes: find the next region. This may leave _coarse_cur_region_index
ysr@777 1200 // Set to the last index, in which case there are no more coarse
ysr@777 1201 // regions.
ysr@777 1202 _coarse_cur_region_index =
ysr@777 1203 (int) _coarse_map->get_next_one_offset(_coarse_cur_region_index + 1);
ysr@777 1204 if ((size_t)_coarse_cur_region_index < _coarse_map->size()) {
ysr@777 1205 _coarse_cur_region_cur_card = 0;
ysr@777 1206 HeapWord* r_bot =
ysr@777 1207 _g1h->region_at(_coarse_cur_region_index)->bottom();
ysr@777 1208 _cur_region_card_offset = _bosa->index_for(r_bot);
ysr@777 1209 } else {
ysr@777 1210 return false;
ysr@777 1211 }
ysr@777 1212 }
ysr@777 1213 // If we didn't return false above, then we can yield a card.
ysr@777 1214 card_index = _cur_region_card_offset + _coarse_cur_region_cur_card;
ysr@777 1215 return true;
ysr@777 1216 }
ysr@777 1217
ysr@777 1218 void HeapRegionRemSetIterator::fine_find_next_non_null_prt() {
ysr@777 1219 // Otherwise, find the next bucket list in the array.
ysr@777 1220 _fine_array_index++;
ysr@777 1221 while (_fine_array_index < (int) OtherRegionsTable::_max_fine_entries) {
ysr@777 1222 _fine_cur_prt = _fine_grain_regions[_fine_array_index];
ysr@777 1223 if (_fine_cur_prt != NULL) return;
ysr@777 1224 else _fine_array_index++;
ysr@777 1225 }
ysr@777 1226 assert(_fine_cur_prt == NULL, "Loop post");
ysr@777 1227 }
ysr@777 1228
ysr@777 1229 bool HeapRegionRemSetIterator::fine_has_next(size_t& card_index) {
ysr@777 1230 if (fine_has_next()) {
ysr@777 1231 _cur_region_cur_card =
ysr@777 1232 _fine_cur_prt->_bm.get_next_one_offset(_cur_region_cur_card + 1);
ysr@777 1233 }
ysr@777 1234 while (!fine_has_next()) {
ysr@777 1235 if (_cur_region_cur_card == PosParPRT::CardsPerRegion) {
ysr@777 1236 _cur_region_cur_card = 0;
ysr@777 1237 _fine_cur_prt = _fine_cur_prt->next();
ysr@777 1238 }
ysr@777 1239 if (_fine_cur_prt == NULL) {
ysr@777 1240 fine_find_next_non_null_prt();
ysr@777 1241 if (_fine_cur_prt == NULL) return false;
ysr@777 1242 }
ysr@777 1243 assert(_fine_cur_prt != NULL && _cur_region_cur_card == 0,
ysr@777 1244 "inv.");
ysr@777 1245 HeapWord* r_bot =
ysr@777 1246 _fine_cur_prt->hr()->bottom();
ysr@777 1247 _cur_region_card_offset = _bosa->index_for(r_bot);
ysr@777 1248 _cur_region_cur_card = _fine_cur_prt->_bm.get_next_one_offset(0);
ysr@777 1249 }
ysr@777 1250 assert(fine_has_next(), "Or else we exited the loop via the return.");
ysr@777 1251 card_index = _cur_region_card_offset + _cur_region_cur_card;
ysr@777 1252 return true;
ysr@777 1253 }
ysr@777 1254
ysr@777 1255 bool HeapRegionRemSetIterator::fine_has_next() {
ysr@777 1256 return
ysr@777 1257 _fine_cur_prt != NULL &&
ysr@777 1258 _cur_region_cur_card < PosParPRT::CardsPerRegion;
ysr@777 1259 }
ysr@777 1260
ysr@777 1261 bool HeapRegionRemSetIterator::has_next(size_t& card_index) {
ysr@777 1262 switch (_is) {
ysr@777 1263 case Sparse:
ysr@777 1264 if (_sparse_iter.has_next(card_index)) {
ysr@777 1265 _n_yielded_sparse++;
ysr@777 1266 return true;
ysr@777 1267 }
ysr@777 1268 // Otherwise, deliberate fall-through
ysr@777 1269 _is = Fine;
ysr@777 1270 case Fine:
ysr@777 1271 if (fine_has_next(card_index)) {
ysr@777 1272 _n_yielded_fine++;
ysr@777 1273 return true;
ysr@777 1274 }
ysr@777 1275 // Otherwise, deliberate fall-through
ysr@777 1276 _is = Coarse;
ysr@777 1277 case Coarse:
ysr@777 1278 if (coarse_has_next(card_index)) {
ysr@777 1279 _n_yielded_coarse++;
ysr@777 1280 return true;
ysr@777 1281 }
ysr@777 1282 // Otherwise...
ysr@777 1283 break;
ysr@777 1284 }
ysr@777 1285 assert(ParallelGCThreads > 1 ||
ysr@777 1286 n_yielded() == _hrrs->occupied(),
ysr@777 1287 "Should have yielded all the cards in the rem set "
ysr@777 1288 "(in the non-par case).");
ysr@777 1289 return false;
ysr@777 1290 }
ysr@777 1291
ysr@777 1292
ysr@777 1293
ysr@1280 1294 OopOrNarrowOopStar* HeapRegionRemSet::_recorded_oops = NULL;
ysr@1280 1295 HeapWord** HeapRegionRemSet::_recorded_cards = NULL;
ysr@1280 1296 HeapRegion** HeapRegionRemSet::_recorded_regions = NULL;
ysr@1280 1297 int HeapRegionRemSet::_n_recorded = 0;
ysr@777 1298
ysr@777 1299 HeapRegionRemSet::Event* HeapRegionRemSet::_recorded_events = NULL;
ysr@777 1300 int* HeapRegionRemSet::_recorded_event_index = NULL;
ysr@777 1301 int HeapRegionRemSet::_n_recorded_events = 0;
ysr@777 1302
ysr@1280 1303 void HeapRegionRemSet::record(HeapRegion* hr, OopOrNarrowOopStar f) {
ysr@777 1304 if (_recorded_oops == NULL) {
ysr@777 1305 assert(_n_recorded == 0
ysr@777 1306 && _recorded_cards == NULL
ysr@777 1307 && _recorded_regions == NULL,
ysr@777 1308 "Inv");
ysr@1280 1309 _recorded_oops = NEW_C_HEAP_ARRAY(OopOrNarrowOopStar, MaxRecorded);
ysr@1280 1310 _recorded_cards = NEW_C_HEAP_ARRAY(HeapWord*, MaxRecorded);
ysr@1280 1311 _recorded_regions = NEW_C_HEAP_ARRAY(HeapRegion*, MaxRecorded);
ysr@777 1312 }
ysr@777 1313 if (_n_recorded == MaxRecorded) {
ysr@777 1314 gclog_or_tty->print_cr("Filled up 'recorded' (%d).", MaxRecorded);
ysr@777 1315 } else {
ysr@777 1316 _recorded_cards[_n_recorded] =
ysr@777 1317 (HeapWord*)align_size_down(uintptr_t(f),
ysr@777 1318 CardTableModRefBS::card_size);
ysr@777 1319 _recorded_oops[_n_recorded] = f;
ysr@777 1320 _recorded_regions[_n_recorded] = hr;
ysr@777 1321 _n_recorded++;
ysr@777 1322 }
ysr@777 1323 }
ysr@777 1324
ysr@777 1325 void HeapRegionRemSet::record_event(Event evnt) {
ysr@777 1326 if (!G1RecordHRRSEvents) return;
ysr@777 1327
ysr@777 1328 if (_recorded_events == NULL) {
ysr@777 1329 assert(_n_recorded_events == 0
ysr@777 1330 && _recorded_event_index == NULL,
ysr@777 1331 "Inv");
ysr@777 1332 _recorded_events = NEW_C_HEAP_ARRAY(Event, MaxRecordedEvents);
ysr@777 1333 _recorded_event_index = NEW_C_HEAP_ARRAY(int, MaxRecordedEvents);
ysr@777 1334 }
ysr@777 1335 if (_n_recorded_events == MaxRecordedEvents) {
ysr@777 1336 gclog_or_tty->print_cr("Filled up 'recorded_events' (%d).", MaxRecordedEvents);
ysr@777 1337 } else {
ysr@777 1338 _recorded_events[_n_recorded_events] = evnt;
ysr@777 1339 _recorded_event_index[_n_recorded_events] = _n_recorded;
ysr@777 1340 _n_recorded_events++;
ysr@777 1341 }
ysr@777 1342 }
ysr@777 1343
ysr@777 1344 void HeapRegionRemSet::print_event(outputStream* str, Event evnt) {
ysr@777 1345 switch (evnt) {
ysr@777 1346 case Event_EvacStart:
ysr@777 1347 str->print("Evac Start");
ysr@777 1348 break;
ysr@777 1349 case Event_EvacEnd:
ysr@777 1350 str->print("Evac End");
ysr@777 1351 break;
ysr@777 1352 case Event_RSUpdateEnd:
ysr@777 1353 str->print("RS Update End");
ysr@777 1354 break;
ysr@777 1355 }
ysr@777 1356 }
ysr@777 1357
ysr@777 1358 void HeapRegionRemSet::print_recorded() {
ysr@777 1359 int cur_evnt = 0;
ysr@777 1360 Event cur_evnt_kind;
ysr@777 1361 int cur_evnt_ind = 0;
ysr@777 1362 if (_n_recorded_events > 0) {
ysr@777 1363 cur_evnt_kind = _recorded_events[cur_evnt];
ysr@777 1364 cur_evnt_ind = _recorded_event_index[cur_evnt];
ysr@777 1365 }
ysr@777 1366
ysr@777 1367 for (int i = 0; i < _n_recorded; i++) {
ysr@777 1368 while (cur_evnt < _n_recorded_events && i == cur_evnt_ind) {
ysr@777 1369 gclog_or_tty->print("Event: ");
ysr@777 1370 print_event(gclog_or_tty, cur_evnt_kind);
ysr@777 1371 gclog_or_tty->print_cr("");
ysr@777 1372 cur_evnt++;
ysr@777 1373 if (cur_evnt < MaxRecordedEvents) {
ysr@777 1374 cur_evnt_kind = _recorded_events[cur_evnt];
ysr@777 1375 cur_evnt_ind = _recorded_event_index[cur_evnt];
ysr@777 1376 }
ysr@777 1377 }
ysr@777 1378 gclog_or_tty->print("Added card " PTR_FORMAT " to region [" PTR_FORMAT "...]"
ysr@777 1379 " for ref " PTR_FORMAT ".\n",
ysr@777 1380 _recorded_cards[i], _recorded_regions[i]->bottom(),
ysr@777 1381 _recorded_oops[i]);
ysr@777 1382 }
ysr@777 1383 }
ysr@777 1384
ysr@777 1385 #ifndef PRODUCT
ysr@777 1386 void HeapRegionRemSet::test() {
ysr@777 1387 os::sleep(Thread::current(), (jlong)5000, false);
ysr@777 1388 G1CollectedHeap* g1h = G1CollectedHeap::heap();
ysr@777 1389
ysr@777 1390 // Run with "-XX:G1LogRSRegionEntries=2", so that 1 and 5 end up in same
ysr@777 1391 // hash bucket.
ysr@777 1392 HeapRegion* hr0 = g1h->region_at(0);
ysr@777 1393 HeapRegion* hr1 = g1h->region_at(1);
ysr@777 1394 HeapRegion* hr2 = g1h->region_at(5);
ysr@777 1395 HeapRegion* hr3 = g1h->region_at(6);
ysr@777 1396 HeapRegion* hr4 = g1h->region_at(7);
ysr@777 1397 HeapRegion* hr5 = g1h->region_at(8);
ysr@777 1398
ysr@777 1399 HeapWord* hr1_start = hr1->bottom();
ysr@777 1400 HeapWord* hr1_mid = hr1_start + HeapRegion::GrainWords/2;
ysr@777 1401 HeapWord* hr1_last = hr1->end() - 1;
ysr@777 1402
ysr@777 1403 HeapWord* hr2_start = hr2->bottom();
ysr@777 1404 HeapWord* hr2_mid = hr2_start + HeapRegion::GrainWords/2;
ysr@777 1405 HeapWord* hr2_last = hr2->end() - 1;
ysr@777 1406
ysr@777 1407 HeapWord* hr3_start = hr3->bottom();
ysr@777 1408 HeapWord* hr3_mid = hr3_start + HeapRegion::GrainWords/2;
ysr@777 1409 HeapWord* hr3_last = hr3->end() - 1;
ysr@777 1410
ysr@777 1411 HeapRegionRemSet* hrrs = hr0->rem_set();
ysr@777 1412
ysr@777 1413 // Make three references from region 0x101...
ysr@1280 1414 hrrs->add_reference((OopOrNarrowOopStar)hr1_start);
ysr@1280 1415 hrrs->add_reference((OopOrNarrowOopStar)hr1_mid);
ysr@1280 1416 hrrs->add_reference((OopOrNarrowOopStar)hr1_last);
ysr@777 1417
ysr@1280 1418 hrrs->add_reference((OopOrNarrowOopStar)hr2_start);
ysr@1280 1419 hrrs->add_reference((OopOrNarrowOopStar)hr2_mid);
ysr@1280 1420 hrrs->add_reference((OopOrNarrowOopStar)hr2_last);
ysr@777 1421
ysr@1280 1422 hrrs->add_reference((OopOrNarrowOopStar)hr3_start);
ysr@1280 1423 hrrs->add_reference((OopOrNarrowOopStar)hr3_mid);
ysr@1280 1424 hrrs->add_reference((OopOrNarrowOopStar)hr3_last);
ysr@777 1425
ysr@777 1426 // Now cause a coarsening.
ysr@1280 1427 hrrs->add_reference((OopOrNarrowOopStar)hr4->bottom());
ysr@1280 1428 hrrs->add_reference((OopOrNarrowOopStar)hr5->bottom());
ysr@777 1429
ysr@777 1430 // Now, does iteration yield these three?
ysr@777 1431 HeapRegionRemSetIterator iter;
ysr@777 1432 hrrs->init_iterator(&iter);
ysr@777 1433 size_t sum = 0;
ysr@777 1434 size_t card_index;
ysr@777 1435 while (iter.has_next(card_index)) {
ysr@777 1436 HeapWord* card_start =
ysr@777 1437 G1CollectedHeap::heap()->bot_shared()->address_for_index(card_index);
ysr@777 1438 gclog_or_tty->print_cr(" Card " PTR_FORMAT ".", card_start);
ysr@777 1439 sum++;
ysr@777 1440 }
ysr@777 1441 guarantee(sum == 11 - 3 + 2048, "Failure");
ysr@777 1442 guarantee(sum == hrrs->occupied(), "Failure");
ysr@777 1443 }
ysr@777 1444 #endif

mercurial