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

Mon, 02 Aug 2010 12:51:43 -0700

author
johnc
date
Mon, 02 Aug 2010 12:51:43 -0700
changeset 2060
2d160770d2e5
parent 2021
5cbac8938c4c
child 2063
a03ae377b2e8
permissions
-rw-r--r--

6814437: G1: remove the _new_refs array
Summary: The per-worker _new_refs array is used to hold references that point into the collection set. It is populated during RSet updating and subsequently processed. In the event of an evacuation failure it processed again to recreate the RSets of regions in the collection set. Remove the per-worker _new_refs array by processing the references directly. Use a DirtyCardQueue to hold the cards containing the references so that the RSets of regions in the collection set can be recreated when handling an evacuation failure.
Reviewed-by: iveresov, jmasa, tonyp

ysr@777 1 /*
johnc@2021 2 * Copyright (c) 2001, 2010, 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
ysr@777 25 #include "incls/_precompiled.incl"
ysr@777 26 #include "incls/_g1RemSet.cpp.incl"
ysr@777 27
ysr@777 28 #define CARD_REPEAT_HISTO 0
ysr@777 29
ysr@777 30 #if CARD_REPEAT_HISTO
ysr@777 31 static size_t ct_freq_sz;
ysr@777 32 static jbyte* ct_freq = NULL;
ysr@777 33
ysr@777 34 void init_ct_freq_table(size_t heap_sz_bytes) {
ysr@777 35 if (ct_freq == NULL) {
ysr@777 36 ct_freq_sz = heap_sz_bytes/CardTableModRefBS::card_size;
ysr@777 37 ct_freq = new jbyte[ct_freq_sz];
ysr@777 38 for (size_t j = 0; j < ct_freq_sz; j++) ct_freq[j] = 0;
ysr@777 39 }
ysr@777 40 }
ysr@777 41
ysr@777 42 void ct_freq_note_card(size_t index) {
ysr@777 43 assert(0 <= index && index < ct_freq_sz, "Bounds error.");
ysr@777 44 if (ct_freq[index] < 100) { ct_freq[index]++; }
ysr@777 45 }
ysr@777 46
ysr@777 47 static IntHistogram card_repeat_count(10, 10);
ysr@777 48
ysr@777 49 void ct_freq_update_histo_and_reset() {
ysr@777 50 for (size_t j = 0; j < ct_freq_sz; j++) {
ysr@777 51 card_repeat_count.add_entry(ct_freq[j]);
ysr@777 52 ct_freq[j] = 0;
ysr@777 53 }
ysr@777 54
ysr@777 55 }
ysr@777 56 #endif
ysr@777 57
ysr@777 58
ysr@777 59 class IntoCSOopClosure: public OopsInHeapRegionClosure {
ysr@777 60 OopsInHeapRegionClosure* _blk;
ysr@777 61 G1CollectedHeap* _g1;
ysr@777 62 public:
ysr@777 63 IntoCSOopClosure(G1CollectedHeap* g1, OopsInHeapRegionClosure* blk) :
ysr@777 64 _g1(g1), _blk(blk) {}
ysr@777 65 void set_region(HeapRegion* from) {
ysr@777 66 _blk->set_region(from);
ysr@777 67 }
ysr@1280 68 virtual void do_oop(narrowOop* p) { do_oop_work(p); }
ysr@1280 69 virtual void do_oop( oop* p) { do_oop_work(p); }
ysr@1280 70 template <class T> void do_oop_work(T* p) {
ysr@1280 71 oop obj = oopDesc::load_decode_heap_oop(p);
ysr@777 72 if (_g1->obj_in_cs(obj)) _blk->do_oop(p);
ysr@777 73 }
ysr@777 74 bool apply_to_weak_ref_discovered_field() { return true; }
ysr@777 75 bool idempotent() { return true; }
ysr@777 76 };
ysr@777 77
ysr@777 78 class IntoCSRegionClosure: public HeapRegionClosure {
ysr@777 79 IntoCSOopClosure _blk;
ysr@777 80 G1CollectedHeap* _g1;
ysr@777 81 public:
ysr@777 82 IntoCSRegionClosure(G1CollectedHeap* g1, OopsInHeapRegionClosure* blk) :
ysr@777 83 _g1(g1), _blk(g1, blk) {}
ysr@777 84 bool doHeapRegion(HeapRegion* r) {
ysr@777 85 if (!r->in_collection_set()) {
ysr@777 86 _blk.set_region(r);
ysr@777 87 if (r->isHumongous()) {
ysr@777 88 if (r->startsHumongous()) {
ysr@777 89 oop obj = oop(r->bottom());
ysr@777 90 obj->oop_iterate(&_blk);
ysr@777 91 }
ysr@777 92 } else {
ysr@777 93 r->oop_before_save_marks_iterate(&_blk);
ysr@777 94 }
ysr@777 95 }
ysr@777 96 return false;
ysr@777 97 }
ysr@777 98 };
ysr@777 99
ysr@777 100 void
ysr@777 101 StupidG1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
ysr@777 102 int worker_i) {
ysr@777 103 IntoCSRegionClosure rc(_g1, oc);
ysr@777 104 _g1->heap_region_iterate(&rc);
ysr@777 105 }
ysr@777 106
ysr@777 107 class VerifyRSCleanCardOopClosure: public OopClosure {
ysr@777 108 G1CollectedHeap* _g1;
ysr@777 109 public:
ysr@777 110 VerifyRSCleanCardOopClosure(G1CollectedHeap* g1) : _g1(g1) {}
ysr@777 111
ysr@1280 112 virtual void do_oop(narrowOop* p) { do_oop_work(p); }
ysr@1280 113 virtual void do_oop( oop* p) { do_oop_work(p); }
ysr@1280 114 template <class T> void do_oop_work(T* p) {
ysr@1280 115 oop obj = oopDesc::load_decode_heap_oop(p);
ysr@777 116 HeapRegion* to = _g1->heap_region_containing(obj);
ysr@777 117 guarantee(to == NULL || !to->in_collection_set(),
ysr@777 118 "Missed a rem set member.");
ysr@777 119 }
ysr@777 120 };
ysr@777 121
ysr@777 122 HRInto_G1RemSet::HRInto_G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs)
ysr@777 123 : G1RemSet(g1), _ct_bs(ct_bs), _g1p(_g1->g1_policy()),
ysr@777 124 _cg1r(g1->concurrent_g1_refine()),
johnc@2060 125 _par_traversal_in_progress(false),
johnc@2060 126 _cset_rs_update_cl(NULL),
ysr@777 127 _cards_scanned(NULL), _total_cards_scanned(0)
ysr@777 128 {
ysr@777 129 _seq_task = new SubTasksDone(NumSeqTasks);
iveresov@1051 130 guarantee(n_workers() > 0, "There should be some workers");
johnc@2060 131 _cset_rs_update_cl = NEW_C_HEAP_ARRAY(OopsInHeapRegionClosure*, n_workers());
iveresov@1051 132 for (uint i = 0; i < n_workers(); i++) {
johnc@2060 133 _cset_rs_update_cl[i] = NULL;
iveresov@1051 134 }
ysr@777 135 }
ysr@777 136
ysr@777 137 HRInto_G1RemSet::~HRInto_G1RemSet() {
ysr@777 138 delete _seq_task;
iveresov@1051 139 for (uint i = 0; i < n_workers(); i++) {
johnc@2060 140 assert(_cset_rs_update_cl[i] == NULL, "it should be");
iveresov@1051 141 }
johnc@2060 142 FREE_C_HEAP_ARRAY(OopsInHeapRegionClosure*, _cset_rs_update_cl);
ysr@777 143 }
ysr@777 144
ysr@777 145 void CountNonCleanMemRegionClosure::do_MemRegion(MemRegion mr) {
ysr@777 146 if (_g1->is_in_g1_reserved(mr.start())) {
ysr@777 147 _n += (int) ((mr.byte_size() / CardTableModRefBS::card_size));
ysr@777 148 if (_start_first == NULL) _start_first = mr.start();
ysr@777 149 }
ysr@777 150 }
ysr@777 151
ysr@777 152 class ScanRSClosure : public HeapRegionClosure {
ysr@777 153 size_t _cards_done, _cards;
ysr@777 154 G1CollectedHeap* _g1h;
ysr@777 155 OopsInHeapRegionClosure* _oc;
ysr@777 156 G1BlockOffsetSharedArray* _bot_shared;
ysr@777 157 CardTableModRefBS *_ct_bs;
ysr@777 158 int _worker_i;
iveresov@1696 159 int _block_size;
ysr@777 160 bool _try_claimed;
ysr@777 161 public:
ysr@777 162 ScanRSClosure(OopsInHeapRegionClosure* oc, int worker_i) :
ysr@777 163 _oc(oc),
ysr@777 164 _cards(0),
ysr@777 165 _cards_done(0),
ysr@777 166 _worker_i(worker_i),
ysr@777 167 _try_claimed(false)
ysr@777 168 {
ysr@777 169 _g1h = G1CollectedHeap::heap();
ysr@777 170 _bot_shared = _g1h->bot_shared();
ysr@777 171 _ct_bs = (CardTableModRefBS*) (_g1h->barrier_set());
iveresov@1696 172 _block_size = MAX2<int>(G1RSetScanBlockSize, 1);
ysr@777 173 }
ysr@777 174
ysr@777 175 void set_try_claimed() { _try_claimed = true; }
ysr@777 176
ysr@777 177 void scanCard(size_t index, HeapRegion *r) {
ysr@777 178 _cards_done++;
ysr@777 179 DirtyCardToOopClosure* cl =
ysr@777 180 r->new_dcto_closure(_oc,
ysr@777 181 CardTableModRefBS::Precise,
ysr@777 182 HeapRegionDCTOC::IntoCSFilterKind);
ysr@777 183
ysr@777 184 // Set the "from" region in the closure.
ysr@777 185 _oc->set_region(r);
ysr@777 186 HeapWord* card_start = _bot_shared->address_for_index(index);
ysr@777 187 HeapWord* card_end = card_start + G1BlockOffsetSharedArray::N_words;
ysr@777 188 Space *sp = SharedHeap::heap()->space_containing(card_start);
ysr@777 189 MemRegion sm_region;
ysr@777 190 if (ParallelGCThreads > 0) {
ysr@777 191 // first find the used area
ysr@777 192 sm_region = sp->used_region_at_save_marks();
ysr@777 193 } else {
ysr@777 194 // The closure is not idempotent. We shouldn't look at objects
ysr@777 195 // allocated during the GC.
ysr@777 196 sm_region = sp->used_region_at_save_marks();
ysr@777 197 }
ysr@777 198 MemRegion mr = sm_region.intersection(MemRegion(card_start,card_end));
ysr@777 199 if (!mr.is_empty()) {
ysr@777 200 cl->do_MemRegion(mr);
ysr@777 201 }
ysr@777 202 }
ysr@777 203
ysr@777 204 void printCard(HeapRegion* card_region, size_t card_index,
ysr@777 205 HeapWord* card_start) {
ysr@777 206 gclog_or_tty->print_cr("T %d Region [" PTR_FORMAT ", " PTR_FORMAT ") "
ysr@777 207 "RS names card %p: "
ysr@777 208 "[" PTR_FORMAT ", " PTR_FORMAT ")",
ysr@777 209 _worker_i,
ysr@777 210 card_region->bottom(), card_region->end(),
ysr@777 211 card_index,
ysr@777 212 card_start, card_start + G1BlockOffsetSharedArray::N_words);
ysr@777 213 }
ysr@777 214
ysr@777 215 bool doHeapRegion(HeapRegion* r) {
ysr@777 216 assert(r->in_collection_set(), "should only be called on elements of CS.");
ysr@777 217 HeapRegionRemSet* hrrs = r->rem_set();
ysr@777 218 if (hrrs->iter_is_complete()) return false; // All done.
ysr@777 219 if (!_try_claimed && !hrrs->claim_iter()) return false;
apetrusenko@1231 220 _g1h->push_dirty_cards_region(r);
ysr@777 221 // If we didn't return above, then
ysr@777 222 // _try_claimed || r->claim_iter()
ysr@777 223 // is true: either we're supposed to work on claimed-but-not-complete
ysr@777 224 // regions, or we successfully claimed the region.
ysr@777 225 HeapRegionRemSetIterator* iter = _g1h->rem_set_iterator(_worker_i);
ysr@777 226 hrrs->init_iterator(iter);
ysr@777 227 size_t card_index;
iveresov@1696 228
iveresov@1696 229 // We claim cards in block so as to recude the contention. The block size is determined by
iveresov@1696 230 // the G1RSetScanBlockSize parameter.
iveresov@1696 231 size_t jump_to_card = hrrs->iter_claimed_next(_block_size);
iveresov@1696 232 for (size_t current_card = 0; iter->has_next(card_index); current_card++) {
iveresov@1696 233 if (current_card >= jump_to_card + _block_size) {
iveresov@1696 234 jump_to_card = hrrs->iter_claimed_next(_block_size);
iveresov@1182 235 }
iveresov@1696 236 if (current_card < jump_to_card) continue;
ysr@777 237 HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index);
ysr@777 238 #if 0
ysr@777 239 gclog_or_tty->print("Rem set iteration yielded card [" PTR_FORMAT ", " PTR_FORMAT ").\n",
ysr@777 240 card_start, card_start + CardTableModRefBS::card_size_in_words);
ysr@777 241 #endif
ysr@777 242
ysr@777 243 HeapRegion* card_region = _g1h->heap_region_containing(card_start);
ysr@777 244 assert(card_region != NULL, "Yielding cards not in the heap?");
ysr@777 245 _cards++;
ysr@777 246
apetrusenko@1231 247 if (!card_region->is_on_dirty_cards_region_list()) {
apetrusenko@1231 248 _g1h->push_dirty_cards_region(card_region);
apetrusenko@1231 249 }
apetrusenko@1231 250
iveresov@1182 251 // If the card is dirty, then we will scan it during updateRS.
iveresov@1182 252 if (!card_region->in_collection_set() && !_ct_bs->is_card_dirty(card_index)) {
iveresov@1696 253 // We make the card as "claimed" lazily (so races are possible but they're benign),
iveresov@1696 254 // which reduces the number of duplicate scans (the rsets of the regions in the cset
iveresov@1696 255 // can intersect).
iveresov@1696 256 if (!_ct_bs->is_card_claimed(card_index)) {
iveresov@1696 257 _ct_bs->set_card_claimed(card_index);
iveresov@1696 258 scanCard(card_index, card_region);
iveresov@1696 259 }
ysr@777 260 }
ysr@777 261 }
iveresov@1182 262 if (!_try_claimed) {
iveresov@1182 263 hrrs->set_iter_complete();
iveresov@1182 264 }
ysr@777 265 return false;
ysr@777 266 }
ysr@777 267 // Set all cards back to clean.
ysr@777 268 void cleanup() {_g1h->cleanUpCardTable();}
ysr@777 269 size_t cards_done() { return _cards_done;}
ysr@777 270 size_t cards_looked_up() { return _cards;}
ysr@777 271 };
ysr@777 272
ysr@777 273 // We want the parallel threads to start their scanning at
ysr@777 274 // different collection set regions to avoid contention.
ysr@777 275 // If we have:
ysr@777 276 // n collection set regions
ysr@777 277 // p threads
ysr@777 278 // Then thread t will start at region t * floor (n/p)
ysr@777 279
ysr@777 280 HeapRegion* HRInto_G1RemSet::calculateStartRegion(int worker_i) {
ysr@777 281 HeapRegion* result = _g1p->collection_set();
ysr@777 282 if (ParallelGCThreads > 0) {
ysr@777 283 size_t cs_size = _g1p->collection_set_size();
ysr@777 284 int n_workers = _g1->workers()->total_workers();
ysr@777 285 size_t cs_spans = cs_size / n_workers;
ysr@777 286 size_t ind = cs_spans * worker_i;
ysr@777 287 for (size_t i = 0; i < ind; i++)
ysr@777 288 result = result->next_in_collection_set();
ysr@777 289 }
ysr@777 290 return result;
ysr@777 291 }
ysr@777 292
ysr@777 293 void HRInto_G1RemSet::scanRS(OopsInHeapRegionClosure* oc, int worker_i) {
ysr@777 294 double rs_time_start = os::elapsedTime();
ysr@777 295 HeapRegion *startRegion = calculateStartRegion(worker_i);
ysr@777 296
iveresov@1696 297 ScanRSClosure scanRScl(oc, worker_i);
ysr@777 298 _g1->collection_set_iterate_from(startRegion, &scanRScl);
ysr@777 299 scanRScl.set_try_claimed();
ysr@777 300 _g1->collection_set_iterate_from(startRegion, &scanRScl);
ysr@777 301
iveresov@1696 302 double scan_rs_time_sec = os::elapsedTime() - rs_time_start;
ysr@777 303
ysr@777 304 assert( _cards_scanned != NULL, "invariant" );
ysr@777 305 _cards_scanned[worker_i] = scanRScl.cards_done();
ysr@777 306
ysr@777 307 _g1p->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
ysr@777 308 }
ysr@777 309
johnc@2060 310 // Closure used for updating RSets and recording references that
johnc@2060 311 // point into the collection set. Only called during an
johnc@2060 312 // evacuation pause.
ysr@777 313
johnc@2060 314 class RefineRecordRefsIntoCSCardTableEntryClosure: public CardTableEntryClosure {
johnc@2060 315 G1RemSet* _g1rs;
johnc@2060 316 DirtyCardQueue* _into_cset_dcq;
johnc@2060 317 public:
johnc@2060 318 RefineRecordRefsIntoCSCardTableEntryClosure(G1CollectedHeap* g1h,
johnc@2060 319 DirtyCardQueue* into_cset_dcq) :
johnc@2060 320 _g1rs(g1h->g1_rem_set()), _into_cset_dcq(into_cset_dcq)
johnc@2060 321 {}
johnc@2060 322 bool do_card_ptr(jbyte* card_ptr, int worker_i) {
johnc@2060 323 // The only time we care about recording cards that
johnc@2060 324 // contain references that point into the collection set
johnc@2060 325 // is during RSet updating within an evacuation pause.
johnc@2060 326 // In this case worker_i should be the id of a GC worker thread.
johnc@2060 327 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
johnc@2060 328 assert(worker_i < (int) DirtyCardQueueSet::num_par_ids(), "should be a GC worker");
johnc@2060 329
johnc@2060 330 if (_g1rs->concurrentRefineOneCard(card_ptr, worker_i, true)) {
johnc@2060 331 // 'card_ptr' contains references that point into the collection
johnc@2060 332 // set. We need to record the card in the DCQS
johnc@2060 333 // (G1CollectedHeap::into_cset_dirty_card_queue_set())
johnc@2060 334 // that's used for that purpose.
johnc@2060 335 //
johnc@2060 336 // Enqueue the card
johnc@2060 337 _into_cset_dcq->enqueue(card_ptr);
johnc@2060 338 }
johnc@2060 339 return true;
johnc@2060 340 }
johnc@2060 341 };
johnc@2060 342
johnc@2060 343 void HRInto_G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) {
ysr@777 344 double start = os::elapsedTime();
johnc@2060 345 // Apply the given closure to all remaining log entries.
johnc@2060 346 RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
johnc@2060 347 _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i);
johnc@2060 348
iveresov@1229 349 // Now there should be no dirty cards.
iveresov@1229 350 if (G1RSLogCheckCardTable) {
iveresov@1229 351 CountNonCleanMemRegionClosure cl(_g1);
iveresov@1229 352 _ct_bs->mod_card_iterate(&cl);
iveresov@1229 353 // XXX This isn't true any more: keeping cards of young regions
iveresov@1229 354 // marked dirty broke it. Need some reasonable fix.
iveresov@1229 355 guarantee(cl.n() == 0, "Card table should be clean.");
ysr@777 356 }
iveresov@1229 357
ysr@777 358 _g1p->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0);
ysr@777 359 }
ysr@777 360
ysr@777 361 #ifndef PRODUCT
ysr@777 362 class PrintRSClosure : public HeapRegionClosure {
ysr@777 363 int _count;
ysr@777 364 public:
ysr@777 365 PrintRSClosure() : _count(0) {}
ysr@777 366 bool doHeapRegion(HeapRegion* r) {
ysr@777 367 HeapRegionRemSet* hrrs = r->rem_set();
ysr@777 368 _count += (int) hrrs->occupied();
ysr@777 369 if (hrrs->occupied() == 0) {
ysr@777 370 gclog_or_tty->print("Heap Region [" PTR_FORMAT ", " PTR_FORMAT ") "
ysr@777 371 "has no remset entries\n",
ysr@777 372 r->bottom(), r->end());
ysr@777 373 } else {
ysr@777 374 gclog_or_tty->print("Printing rem set for heap region [" PTR_FORMAT ", " PTR_FORMAT ")\n",
ysr@777 375 r->bottom(), r->end());
ysr@777 376 r->print();
ysr@777 377 hrrs->print();
ysr@777 378 gclog_or_tty->print("\nDone printing rem set\n");
ysr@777 379 }
ysr@777 380 return false;
ysr@777 381 }
ysr@777 382 int occupied() {return _count;}
ysr@777 383 };
ysr@777 384 #endif
ysr@777 385
ysr@777 386 class CountRSSizeClosure: public HeapRegionClosure {
ysr@777 387 size_t _n;
ysr@777 388 size_t _tot;
ysr@777 389 size_t _max;
ysr@777 390 HeapRegion* _max_r;
ysr@777 391 enum {
ysr@777 392 N = 20,
ysr@777 393 MIN = 6
ysr@777 394 };
ysr@777 395 int _histo[N];
ysr@777 396 public:
ysr@777 397 CountRSSizeClosure() : _n(0), _tot(0), _max(0), _max_r(NULL) {
ysr@777 398 for (int i = 0; i < N; i++) _histo[i] = 0;
ysr@777 399 }
ysr@777 400 bool doHeapRegion(HeapRegion* r) {
ysr@777 401 if (!r->continuesHumongous()) {
ysr@777 402 size_t occ = r->rem_set()->occupied();
ysr@777 403 _n++;
ysr@777 404 _tot += occ;
ysr@777 405 if (occ > _max) {
ysr@777 406 _max = occ;
ysr@777 407 _max_r = r;
ysr@777 408 }
ysr@777 409 // Fit it into a histo bin.
ysr@777 410 int s = 1 << MIN;
ysr@777 411 int i = 0;
ysr@777 412 while (occ > (size_t) s && i < (N-1)) {
ysr@777 413 s = s << 1;
ysr@777 414 i++;
ysr@777 415 }
ysr@777 416 _histo[i]++;
ysr@777 417 }
ysr@777 418 return false;
ysr@777 419 }
ysr@777 420 size_t n() { return _n; }
ysr@777 421 size_t tot() { return _tot; }
ysr@777 422 size_t mx() { return _max; }
ysr@777 423 HeapRegion* mxr() { return _max_r; }
ysr@777 424 void print_histo() {
ysr@777 425 int mx = N;
ysr@777 426 while (mx >= 0) {
ysr@777 427 if (_histo[mx-1] > 0) break;
ysr@777 428 mx--;
ysr@777 429 }
ysr@777 430 gclog_or_tty->print_cr("Number of regions with given RS sizes:");
ysr@777 431 gclog_or_tty->print_cr(" <= %8d %8d", 1 << MIN, _histo[0]);
ysr@777 432 for (int i = 1; i < mx-1; i++) {
ysr@777 433 gclog_or_tty->print_cr(" %8d - %8d %8d",
ysr@777 434 (1 << (MIN + i - 1)) + 1,
ysr@777 435 1 << (MIN + i),
ysr@777 436 _histo[i]);
ysr@777 437 }
ysr@777 438 gclog_or_tty->print_cr(" > %8d %8d", (1 << (MIN+mx-2))+1, _histo[mx-1]);
ysr@777 439 }
ysr@777 440 };
ysr@777 441
ysr@777 442 void HRInto_G1RemSet::cleanupHRRS() {
ysr@777 443 HeapRegionRemSet::cleanup();
ysr@777 444 }
ysr@777 445
ysr@777 446 void
ysr@777 447 HRInto_G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
ysr@777 448 int worker_i) {
ysr@777 449 #if CARD_REPEAT_HISTO
ysr@777 450 ct_freq_update_histo_and_reset();
ysr@777 451 #endif
ysr@777 452 if (worker_i == 0) {
ysr@777 453 _cg1r->clear_and_record_card_counts();
ysr@777 454 }
ysr@777 455
ysr@777 456 // Make this into a command-line flag...
ysr@777 457 if (G1RSCountHisto && (ParallelGCThreads == 0 || worker_i == 0)) {
ysr@777 458 CountRSSizeClosure count_cl;
ysr@777 459 _g1->heap_region_iterate(&count_cl);
ysr@777 460 gclog_or_tty->print_cr("Avg of %d RS counts is %f, max is %d, "
ysr@777 461 "max region is " PTR_FORMAT,
ysr@777 462 count_cl.n(), (float)count_cl.tot()/(float)count_cl.n(),
ysr@777 463 count_cl.mx(), count_cl.mxr());
ysr@777 464 count_cl.print_histo();
ysr@777 465 }
ysr@777 466
johnc@2060 467 // We cache the value of 'oc' closure into the appropriate slot in the
johnc@2060 468 // _cset_rs_update_cl for this worker
johnc@2060 469 assert(worker_i < (int)n_workers(), "sanity");
johnc@2060 470 _cset_rs_update_cl[worker_i] = oc;
johnc@2060 471
johnc@2060 472 // A DirtyCardQueue that is used to hold cards containing references
johnc@2060 473 // that point into the collection set. This DCQ is associated with a
johnc@2060 474 // special DirtyCardQueueSet (see g1CollectedHeap.hpp). Under normal
johnc@2060 475 // circumstances (i.e. the pause successfully completes), these cards
johnc@2060 476 // are just discarded (there's no need to update the RSets of regions
johnc@2060 477 // that were in the collection set - after the pause these regions
johnc@2060 478 // are wholly 'free' of live objects. In the event of an evacuation
johnc@2060 479 // failure the cards/buffers in this queue set are:
johnc@2060 480 // * passed to the DirtyCardQueueSet that is used to manage deferred
johnc@2060 481 // RSet updates, or
johnc@2060 482 // * scanned for references that point into the collection set
johnc@2060 483 // and the RSet of the corresponding region in the collection set
johnc@2060 484 // is updated immediately.
johnc@2060 485 DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
johnc@2060 486
ysr@777 487 if (ParallelGCThreads > 0) {
tonyp@1073 488 // The two flags below were introduced temporarily to serialize
tonyp@1073 489 // the updating and scanning of remembered sets. There are some
tonyp@1073 490 // race conditions when these two operations are done in parallel
tonyp@1073 491 // and they are causing failures. When we resolve said race
tonyp@1073 492 // conditions, we'll revert back to parallel remembered set
tonyp@1073 493 // updating and scanning. See CRs 6677707 and 6677708.
tonyp@1717 494 if (G1UseParallelRSetUpdating || (worker_i == 0)) {
johnc@2060 495 updateRS(&into_cset_dcq, worker_i);
tonyp@1083 496 } else {
tonyp@1083 497 _g1p->record_update_rs_processed_buffers(worker_i, 0.0);
tonyp@1083 498 _g1p->record_update_rs_time(worker_i, 0.0);
tonyp@1073 499 }
tonyp@1717 500 if (G1UseParallelRSetScanning || (worker_i == 0)) {
ysr@777 501 scanRS(oc, worker_i);
tonyp@1083 502 } else {
tonyp@1083 503 _g1p->record_scan_rs_time(worker_i, 0.0);
ysr@777 504 }
ysr@777 505 } else {
ysr@777 506 assert(worker_i == 0, "invariant");
johnc@2060 507 updateRS(&into_cset_dcq, 0);
ysr@777 508 scanRS(oc, 0);
ysr@777 509 }
johnc@2060 510
johnc@2060 511 // We now clear the cached values of _cset_rs_update_cl for this worker
johnc@2060 512 _cset_rs_update_cl[worker_i] = NULL;
ysr@777 513 }
ysr@777 514
ysr@777 515 void HRInto_G1RemSet::
ysr@777 516 prepare_for_oops_into_collection_set_do() {
ysr@777 517 #if G1_REM_SET_LOGGING
ysr@777 518 PrintRSClosure cl;
ysr@777 519 _g1->collection_set_iterate(&cl);
ysr@777 520 #endif
ysr@777 521 cleanupHRRS();
ysr@777 522 ConcurrentG1Refine* cg1r = _g1->concurrent_g1_refine();
ysr@777 523 _g1->set_refine_cte_cl_concurrency(false);
ysr@777 524 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
ysr@777 525 dcqs.concatenate_logs();
ysr@777 526
ysr@777 527 assert(!_par_traversal_in_progress, "Invariant between iterations.");
ysr@777 528 if (ParallelGCThreads > 0) {
ysr@777 529 set_par_traversal(true);
iveresov@1051 530 _seq_task->set_par_threads((int)n_workers());
ysr@777 531 }
ysr@777 532 guarantee( _cards_scanned == NULL, "invariant" );
ysr@777 533 _cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers());
apetrusenko@980 534 for (uint i = 0; i < n_workers(); ++i) {
apetrusenko@980 535 _cards_scanned[i] = 0;
apetrusenko@980 536 }
ysr@777 537 _total_cards_scanned = 0;
ysr@777 538 }
ysr@777 539
ysr@777 540
ysr@777 541 class cleanUpIteratorsClosure : public HeapRegionClosure {
ysr@777 542 bool doHeapRegion(HeapRegion *r) {
ysr@777 543 HeapRegionRemSet* hrrs = r->rem_set();
ysr@777 544 hrrs->init_for_par_iteration();
ysr@777 545 return false;
ysr@777 546 }
ysr@777 547 };
ysr@777 548
johnc@2060 549 // This closure, applied to a DirtyCardQueueSet, is used to immediately
johnc@2060 550 // update the RSets for the regions in the CSet. For each card it iterates
johnc@2060 551 // through the oops which coincide with that card. It scans the reference
johnc@2060 552 // fields in each oop; when it finds an oop that points into the collection
johnc@2060 553 // set, the RSet for the region containing the referenced object is updated.
johnc@2060 554 // Note: _par_traversal_in_progress in the G1RemSet must be FALSE; otherwise
johnc@2060 555 // the UpdateRSetImmediate closure will cause cards to be enqueued on to
johnc@2060 556 // the DCQS that we're iterating over, causing an infinite loop.
johnc@2060 557 class UpdateRSetCardTableEntryIntoCSetClosure: public CardTableEntryClosure {
iveresov@1051 558 G1CollectedHeap* _g1;
johnc@2060 559 CardTableModRefBS* _ct_bs;
iveresov@1051 560 public:
johnc@2060 561 UpdateRSetCardTableEntryIntoCSetClosure(G1CollectedHeap* g1,
johnc@2060 562 CardTableModRefBS* bs):
johnc@2060 563 _g1(g1), _ct_bs(bs)
johnc@2060 564 { }
johnc@2060 565
johnc@2060 566 bool do_card_ptr(jbyte* card_ptr, int worker_i) {
johnc@2060 567 // Construct the region representing the card.
johnc@2060 568 HeapWord* start = _ct_bs->addr_for(card_ptr);
johnc@2060 569 // And find the region containing it.
johnc@2060 570 HeapRegion* r = _g1->heap_region_containing(start);
johnc@2060 571 assert(r != NULL, "unexpected null");
johnc@2060 572
johnc@2060 573 // Scan oops in the card looking for references into the collection set
johnc@2060 574 HeapWord* end = _ct_bs->addr_for(card_ptr + 1);
johnc@2060 575 MemRegion scanRegion(start, end);
johnc@2060 576
johnc@2060 577 UpdateRSetImmediate update_rs_cl(_g1->g1_rem_set());
johnc@2060 578 FilterIntoCSClosure update_rs_cset_oop_cl(NULL, _g1, &update_rs_cl);
johnc@2060 579 FilterOutOfRegionClosure filter_then_update_rs_cset_oop_cl(r, &update_rs_cset_oop_cl);
johnc@2060 580
johnc@2060 581 // We can pass false as the "filter_young" parameter here as:
johnc@2060 582 // * we should be in a STW pause,
johnc@2060 583 // * the DCQS to which this closure is applied is used to hold
johnc@2060 584 // references that point into the collection set from the prior
johnc@2060 585 // RSet updating,
johnc@2060 586 // * the post-write barrier shouldn't be logging updates to young
johnc@2060 587 // regions (but there is a situation where this can happen - see
johnc@2060 588 // the comment in HRInto_G1RemSet::concurrentRefineOneCard below -
johnc@2060 589 // that should not be applicable here), and
johnc@2060 590 // * during actual RSet updating, the filtering of cards in young
johnc@2060 591 // regions in HeapRegion::oops_on_card_seq_iterate_careful is
johnc@2060 592 // employed.
johnc@2060 593 // As a result, when this closure is applied to "refs into cset"
johnc@2060 594 // DCQS, we shouldn't see any cards in young regions.
johnc@2060 595 update_rs_cl.set_region(r);
johnc@2060 596 HeapWord* stop_point =
johnc@2060 597 r->oops_on_card_seq_iterate_careful(scanRegion,
johnc@2060 598 &filter_then_update_rs_cset_oop_cl,
johnc@2060 599 false /* filter_young */);
johnc@2060 600
johnc@2060 601 // Since this is performed in the event of an evacuation failure, we
johnc@2060 602 // we shouldn't see a non-null stop point
johnc@2060 603 assert(stop_point == NULL, "saw an unallocated region");
johnc@2060 604 return true;
iveresov@1051 605 }
iveresov@1051 606 };
iveresov@1051 607
ysr@777 608 void HRInto_G1RemSet::cleanup_after_oops_into_collection_set_do() {
ysr@777 609 guarantee( _cards_scanned != NULL, "invariant" );
ysr@777 610 _total_cards_scanned = 0;
ysr@777 611 for (uint i = 0; i < n_workers(); ++i)
ysr@777 612 _total_cards_scanned += _cards_scanned[i];
ysr@777 613 FREE_C_HEAP_ARRAY(size_t, _cards_scanned);
ysr@777 614 _cards_scanned = NULL;
ysr@777 615 // Cleanup after copy
ysr@777 616 #if G1_REM_SET_LOGGING
ysr@777 617 PrintRSClosure cl;
ysr@777 618 _g1->heap_region_iterate(&cl);
ysr@777 619 #endif
ysr@777 620 _g1->set_refine_cte_cl_concurrency(true);
ysr@777 621 cleanUpIteratorsClosure iterClosure;
ysr@777 622 _g1->collection_set_iterate(&iterClosure);
ysr@777 623 // Set all cards back to clean.
ysr@777 624 _g1->cleanUpCardTable();
iveresov@1229 625
ysr@777 626 if (ParallelGCThreads > 0) {
ysr@777 627 set_par_traversal(false);
ysr@777 628 }
iveresov@1051 629
johnc@2060 630 DirtyCardQueueSet& into_cset_dcqs = _g1->into_cset_dirty_card_queue_set();
johnc@2060 631 int into_cset_n_buffers = into_cset_dcqs.completed_buffers_num();
johnc@2060 632
iveresov@1051 633 if (_g1->evacuation_failed()) {
johnc@2060 634 // Restore remembered sets for the regions pointing into the collection set.
johnc@2060 635
iveresov@1051 636 if (G1DeferredRSUpdate) {
johnc@2060 637 // If deferred RS updates are enabled then we just need to transfer
johnc@2060 638 // the completed buffers from (a) the DirtyCardQueueSet used to hold
johnc@2060 639 // cards that contain references that point into the collection set
johnc@2060 640 // to (b) the DCQS used to hold the deferred RS updates
johnc@2060 641 _g1->dirty_card_queue_set().merge_bufferlists(&into_cset_dcqs);
iveresov@1051 642 } else {
johnc@2060 643
johnc@2060 644 CardTableModRefBS* bs = (CardTableModRefBS*)_g1->barrier_set();
johnc@2060 645 UpdateRSetCardTableEntryIntoCSetClosure update_rs_cset_immediate(_g1, bs);
johnc@2060 646
johnc@2060 647 int n_completed_buffers = 0;
johnc@2060 648 while (into_cset_dcqs.apply_closure_to_completed_buffer(&update_rs_cset_immediate,
johnc@2060 649 0, 0, true)) {
johnc@2060 650 n_completed_buffers++;
johnc@2060 651 }
johnc@2060 652 assert(n_completed_buffers == into_cset_n_buffers, "missed some buffers");
iveresov@1051 653 }
iveresov@1051 654 }
johnc@2060 655
johnc@2060 656 // Free any completed buffers in the DirtyCardQueueSet used to hold cards
johnc@2060 657 // which contain references that point into the collection.
johnc@2060 658 _g1->into_cset_dirty_card_queue_set().clear();
johnc@2060 659 assert(_g1->into_cset_dirty_card_queue_set().completed_buffers_num() == 0,
johnc@2060 660 "all buffers should be freed");
johnc@2060 661 _g1->into_cset_dirty_card_queue_set().clear_n_completed_buffers();
iveresov@1051 662
ysr@777 663 assert(!_par_traversal_in_progress, "Invariant between iterations.");
ysr@777 664 }
ysr@777 665
ysr@777 666 class UpdateRSObjectClosure: public ObjectClosure {
ysr@777 667 UpdateRSOopClosure* _update_rs_oop_cl;
ysr@777 668 public:
ysr@777 669 UpdateRSObjectClosure(UpdateRSOopClosure* update_rs_oop_cl) :
ysr@777 670 _update_rs_oop_cl(update_rs_oop_cl) {}
ysr@777 671 void do_object(oop obj) {
ysr@777 672 obj->oop_iterate(_update_rs_oop_cl);
ysr@777 673 }
ysr@777 674
ysr@777 675 };
ysr@777 676
ysr@777 677 class ScrubRSClosure: public HeapRegionClosure {
ysr@777 678 G1CollectedHeap* _g1h;
ysr@777 679 BitMap* _region_bm;
ysr@777 680 BitMap* _card_bm;
ysr@777 681 CardTableModRefBS* _ctbs;
ysr@777 682 public:
ysr@777 683 ScrubRSClosure(BitMap* region_bm, BitMap* card_bm) :
ysr@777 684 _g1h(G1CollectedHeap::heap()),
ysr@777 685 _region_bm(region_bm), _card_bm(card_bm),
ysr@777 686 _ctbs(NULL)
ysr@777 687 {
ysr@777 688 ModRefBarrierSet* bs = _g1h->mr_bs();
ysr@777 689 guarantee(bs->is_a(BarrierSet::CardTableModRef), "Precondition");
ysr@777 690 _ctbs = (CardTableModRefBS*)bs;
ysr@777 691 }
ysr@777 692
ysr@777 693 bool doHeapRegion(HeapRegion* r) {
ysr@777 694 if (!r->continuesHumongous()) {
ysr@777 695 r->rem_set()->scrub(_ctbs, _region_bm, _card_bm);
ysr@777 696 }
ysr@777 697 return false;
ysr@777 698 }
ysr@777 699 };
ysr@777 700
ysr@777 701 void HRInto_G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm) {
ysr@777 702 ScrubRSClosure scrub_cl(region_bm, card_bm);
ysr@777 703 _g1->heap_region_iterate(&scrub_cl);
ysr@777 704 }
ysr@777 705
ysr@777 706 void HRInto_G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm,
ysr@777 707 int worker_num, int claim_val) {
ysr@777 708 ScrubRSClosure scrub_cl(region_bm, card_bm);
ysr@777 709 _g1->heap_region_par_iterate_chunked(&scrub_cl, worker_num, claim_val);
ysr@777 710 }
ysr@777 711
ysr@777 712
ysr@777 713 static IntHistogram out_of_histo(50, 50);
ysr@777 714
johnc@2060 715 class TriggerClosure : public OopClosure {
johnc@2060 716 bool _trigger;
johnc@2060 717 public:
johnc@2060 718 TriggerClosure() : _trigger(false) { }
johnc@2060 719 bool value() const { return _trigger; }
johnc@2060 720 template <class T> void do_oop_nv(T* p) { _trigger = true; }
johnc@2060 721 virtual void do_oop(oop* p) { do_oop_nv(p); }
johnc@2060 722 virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
johnc@2060 723 };
johnc@2060 724
johnc@2060 725 class InvokeIfNotTriggeredClosure: public OopClosure {
johnc@2060 726 TriggerClosure* _t;
johnc@2060 727 OopClosure* _oc;
johnc@2060 728 public:
johnc@2060 729 InvokeIfNotTriggeredClosure(TriggerClosure* t, OopClosure* oc):
johnc@2060 730 _t(t), _oc(oc) { }
johnc@2060 731 template <class T> void do_oop_nv(T* p) {
johnc@2060 732 if (!_t->value()) _oc->do_oop(p);
johnc@2060 733 }
johnc@2060 734 virtual void do_oop(oop* p) { do_oop_nv(p); }
johnc@2060 735 virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
johnc@2060 736 };
johnc@2060 737
johnc@2060 738 class Mux2Closure : public OopClosure {
johnc@2060 739 OopClosure* _c1;
johnc@2060 740 OopClosure* _c2;
johnc@2060 741 public:
johnc@2060 742 Mux2Closure(OopClosure *c1, OopClosure *c2) : _c1(c1), _c2(c2) { }
johnc@2060 743 template <class T> void do_oop_nv(T* p) {
johnc@2060 744 _c1->do_oop(p); _c2->do_oop(p);
johnc@2060 745 }
johnc@2060 746 virtual void do_oop(oop* p) { do_oop_nv(p); }
johnc@2060 747 virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
johnc@2060 748 };
johnc@2060 749
johnc@2060 750 bool HRInto_G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i,
johnc@2060 751 bool check_for_refs_into_cset) {
johnc@1325 752 // Construct the region representing the card.
johnc@1325 753 HeapWord* start = _ct_bs->addr_for(card_ptr);
johnc@1325 754 // And find the region containing it.
johnc@1325 755 HeapRegion* r = _g1->heap_region_containing(start);
johnc@1325 756 assert(r != NULL, "unexpected null");
johnc@1325 757
johnc@1325 758 HeapWord* end = _ct_bs->addr_for(card_ptr + 1);
johnc@1325 759 MemRegion dirtyRegion(start, end);
johnc@1325 760
johnc@1325 761 #if CARD_REPEAT_HISTO
johnc@1325 762 init_ct_freq_table(_g1->g1_reserved_obj_bytes());
johnc@1325 763 ct_freq_note_card(_ct_bs->index_for(start));
johnc@1325 764 #endif
johnc@1325 765
johnc@1325 766 UpdateRSOopClosure update_rs_oop_cl(this, worker_i);
johnc@1325 767 update_rs_oop_cl.set_from(r);
johnc@2060 768
johnc@2060 769 TriggerClosure trigger_cl;
johnc@2060 770 FilterIntoCSClosure into_cs_cl(NULL, _g1, &trigger_cl);
johnc@2060 771 InvokeIfNotTriggeredClosure invoke_cl(&trigger_cl, &into_cs_cl);
johnc@2060 772 Mux2Closure mux(&invoke_cl, &update_rs_oop_cl);
johnc@2060 773
johnc@2060 774 FilterOutOfRegionClosure filter_then_update_rs_oop_cl(r,
johnc@2060 775 (check_for_refs_into_cset ?
johnc@2060 776 (OopClosure*)&mux :
johnc@2060 777 (OopClosure*)&update_rs_oop_cl));
johnc@1325 778
johnc@1325 779 // Undirty the card.
johnc@1325 780 *card_ptr = CardTableModRefBS::clean_card_val();
johnc@1325 781 // We must complete this write before we do any of the reads below.
johnc@1325 782 OrderAccess::storeload();
johnc@1325 783 // And process it, being careful of unallocated portions of TLAB's.
johnc@2021 784
johnc@2021 785 // The region for the current card may be a young region. The
johnc@2021 786 // current card may have been a card that was evicted from the
johnc@2021 787 // card cache. When the card was inserted into the cache, we had
johnc@2021 788 // determined that its region was non-young. While in the cache,
johnc@2021 789 // the region may have been freed during a cleanup pause, reallocated
johnc@2021 790 // and tagged as young.
johnc@2021 791 //
johnc@2021 792 // We wish to filter out cards for such a region but the current
johnc@2021 793 // thread, if we're running conucrrently, may "see" the young type
johnc@2021 794 // change at any time (so an earlier "is_young" check may pass or
johnc@2021 795 // fail arbitrarily). We tell the iteration code to perform this
johnc@2021 796 // filtering when it has been determined that there has been an actual
johnc@2021 797 // allocation in this region and making it safe to check the young type.
johnc@2021 798 bool filter_young = true;
johnc@2021 799
johnc@1325 800 HeapWord* stop_point =
johnc@1325 801 r->oops_on_card_seq_iterate_careful(dirtyRegion,
johnc@2021 802 &filter_then_update_rs_oop_cl,
johnc@2021 803 filter_young);
johnc@2021 804
johnc@1325 805 // If stop_point is non-null, then we encountered an unallocated region
johnc@1325 806 // (perhaps the unfilled portion of a TLAB.) For now, we'll dirty the
johnc@1325 807 // card and re-enqueue: if we put off the card until a GC pause, then the
johnc@1325 808 // unallocated portion will be filled in. Alternatively, we might try
johnc@1325 809 // the full complexity of the technique used in "regular" precleaning.
johnc@1325 810 if (stop_point != NULL) {
johnc@1325 811 // The card might have gotten re-dirtied and re-enqueued while we
johnc@1325 812 // worked. (In fact, it's pretty likely.)
johnc@1325 813 if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
johnc@1325 814 *card_ptr = CardTableModRefBS::dirty_card_val();
johnc@1325 815 MutexLockerEx x(Shared_DirtyCardQ_lock,
johnc@1325 816 Mutex::_no_safepoint_check_flag);
johnc@1325 817 DirtyCardQueue* sdcq =
johnc@1325 818 JavaThread::dirty_card_queue_set().shared_dirty_card_queue();
johnc@1325 819 sdcq->enqueue(card_ptr);
johnc@1325 820 }
johnc@1325 821 } else {
johnc@1325 822 out_of_histo.add_entry(filter_then_update_rs_oop_cl.out_of_region());
johnc@1325 823 _conc_refine_cards++;
johnc@1325 824 }
johnc@2060 825
johnc@2060 826 return trigger_cl.value();
johnc@1325 827 }
johnc@1325 828
johnc@2060 829 bool HRInto_G1RemSet::concurrentRefineOneCard(jbyte* card_ptr, int worker_i,
johnc@2060 830 bool check_for_refs_into_cset) {
ysr@777 831 // If the card is no longer dirty, nothing to do.
johnc@2060 832 if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
johnc@2060 833 // No need to return that this card contains refs that point
johnc@2060 834 // into the collection set.
johnc@2060 835 return false;
johnc@2060 836 }
ysr@777 837
ysr@777 838 // Construct the region representing the card.
ysr@777 839 HeapWord* start = _ct_bs->addr_for(card_ptr);
ysr@777 840 // And find the region containing it.
ysr@777 841 HeapRegion* r = _g1->heap_region_containing(start);
ysr@777 842 if (r == NULL) {
ysr@777 843 guarantee(_g1->is_in_permanent(start), "Or else where?");
johnc@2060 844 // Again no need to return that this card contains refs that
johnc@2060 845 // point into the collection set.
johnc@2060 846 return false; // Not in the G1 heap (might be in perm, for example.)
ysr@777 847 }
ysr@777 848 // Why do we have to check here whether a card is on a young region,
ysr@777 849 // given that we dirty young regions and, as a result, the
ysr@777 850 // post-barrier is supposed to filter them out and never to enqueue
ysr@777 851 // them? When we allocate a new region as the "allocation region" we
ysr@777 852 // actually dirty its cards after we release the lock, since card
ysr@777 853 // dirtying while holding the lock was a performance bottleneck. So,
ysr@777 854 // as a result, it is possible for other threads to actually
ysr@777 855 // allocate objects in the region (after the acquire the lock)
ysr@777 856 // before all the cards on the region are dirtied. This is unlikely,
ysr@777 857 // and it doesn't happen often, but it can happen. So, the extra
ysr@777 858 // check below filters out those cards.
iveresov@1072 859 if (r->is_young()) {
johnc@2060 860 return false;
ysr@777 861 }
ysr@777 862 // While we are processing RSet buffers during the collection, we
ysr@777 863 // actually don't want to scan any cards on the collection set,
ysr@777 864 // since we don't want to update remebered sets with entries that
ysr@777 865 // point into the collection set, given that live objects from the
ysr@777 866 // collection set are about to move and such entries will be stale
ysr@777 867 // very soon. This change also deals with a reliability issue which
ysr@777 868 // involves scanning a card in the collection set and coming across
ysr@777 869 // an array that was being chunked and looking malformed. Note,
ysr@777 870 // however, that if evacuation fails, we have to scan any objects
ysr@777 871 // that were not moved and create any missing entries.
ysr@777 872 if (r->in_collection_set()) {
johnc@2060 873 return false;
ysr@777 874 }
ysr@777 875
johnc@1325 876 // Should we defer processing the card?
johnc@1325 877 //
johnc@1325 878 // Previously the result from the insert_cache call would be
johnc@1325 879 // either card_ptr (implying that card_ptr was currently "cold"),
johnc@1325 880 // null (meaning we had inserted the card ptr into the "hot"
johnc@1325 881 // cache, which had some headroom), or a "hot" card ptr
johnc@1325 882 // extracted from the "hot" cache.
johnc@1325 883 //
johnc@1325 884 // Now that the _card_counts cache in the ConcurrentG1Refine
johnc@1325 885 // instance is an evicting hash table, the result we get back
johnc@1325 886 // could be from evicting the card ptr in an already occupied
johnc@1325 887 // bucket (in which case we have replaced the card ptr in the
johnc@1325 888 // bucket with card_ptr and "defer" is set to false). To avoid
johnc@1325 889 // having a data structure (updates to which would need a lock)
johnc@1325 890 // to hold these unprocessed dirty cards, we need to immediately
johnc@1325 891 // process card_ptr. The actions needed to be taken on return
johnc@1325 892 // from cache_insert are summarized in the following table:
johnc@1325 893 //
johnc@1325 894 // res defer action
johnc@1325 895 // --------------------------------------------------------------
johnc@1325 896 // null false card evicted from _card_counts & replaced with
johnc@1325 897 // card_ptr; evicted ptr added to hot cache.
johnc@1325 898 // No need to process res; immediately process card_ptr
johnc@1325 899 //
johnc@1325 900 // null true card not evicted from _card_counts; card_ptr added
johnc@1325 901 // to hot cache.
johnc@1325 902 // Nothing to do.
johnc@1325 903 //
johnc@1325 904 // non-null false card evicted from _card_counts & replaced with
johnc@1325 905 // card_ptr; evicted ptr is currently "cold" or
johnc@1325 906 // caused an eviction from the hot cache.
johnc@1325 907 // Immediately process res; process card_ptr.
johnc@1325 908 //
johnc@1325 909 // non-null true card not evicted from _card_counts; card_ptr is
johnc@1325 910 // currently cold, or caused an eviction from hot
johnc@1325 911 // cache.
johnc@1325 912 // Immediately process res; no need to process card_ptr.
johnc@1325 913
johnc@2060 914
johnc@1325 915 jbyte* res = card_ptr;
johnc@1325 916 bool defer = false;
johnc@2060 917
johnc@2060 918 // This gets set to true if the card being refined has references
johnc@2060 919 // that point into the collection set.
johnc@2060 920 bool oops_into_cset = false;
johnc@2060 921
ysr@777 922 if (_cg1r->use_cache()) {
johnc@1325 923 jbyte* res = _cg1r->cache_insert(card_ptr, &defer);
johnc@1325 924 if (res != NULL && (res != card_ptr || defer)) {
johnc@1325 925 start = _ct_bs->addr_for(res);
johnc@1325 926 r = _g1->heap_region_containing(start);
johnc@1325 927 if (r == NULL) {
johnc@1325 928 assert(_g1->is_in_permanent(start), "Or else where?");
johnc@1325 929 } else {
johnc@2021 930 // Checking whether the region we got back from the cache
johnc@2021 931 // is young here is inappropriate. The region could have been
johnc@2021 932 // freed, reallocated and tagged as young while in the cache.
johnc@2021 933 // Hence we could see its young type change at any time.
johnc@2021 934 //
johnc@2021 935 // Process card pointer we get back from the hot card cache. This
johnc@2021 936 // will check whether the region containing the card is young
johnc@2021 937 // _after_ checking that the region has been allocated from.
johnc@2060 938 oops_into_cset = concurrentRefineOneCard_impl(res, worker_i,
johnc@2060 939 false /* check_for_refs_into_cset */);
johnc@2060 940 // The above call to concurrentRefineOneCard_impl is only
johnc@2060 941 // performed if the hot card cache is enabled. This cache is
johnc@2060 942 // disabled during an evacuation pause - which is the only
johnc@2060 943 // time when we need know if the card contains references
johnc@2060 944 // that point into the collection set. Also when the hot card
johnc@2060 945 // cache is enabled, this code is executed by the concurrent
johnc@2060 946 // refine threads - rather than the GC worker threads - and
johnc@2060 947 // concurrentRefineOneCard_impl will return false.
johnc@2060 948 assert(!oops_into_cset, "should not see true here");
johnc@1325 949 }
ysr@777 950 }
ysr@777 951 }
ysr@777 952
johnc@1325 953 if (!defer) {
johnc@2060 954 oops_into_cset =
johnc@2060 955 concurrentRefineOneCard_impl(card_ptr, worker_i, check_for_refs_into_cset);
johnc@2060 956 // We should only be detecting that the card contains references
johnc@2060 957 // that point into the collection set if the current thread is
johnc@2060 958 // a GC worker thread.
johnc@2060 959 assert(!oops_into_cset || SafepointSynchronize::is_at_safepoint(),
johnc@2060 960 "invalid result at non safepoint");
ysr@777 961 }
johnc@2060 962 return oops_into_cset;
ysr@777 963 }
ysr@777 964
ysr@777 965 class HRRSStatsIter: public HeapRegionClosure {
ysr@777 966 size_t _occupied;
ysr@777 967 size_t _total_mem_sz;
ysr@777 968 size_t _max_mem_sz;
ysr@777 969 HeapRegion* _max_mem_sz_region;
ysr@777 970 public:
ysr@777 971 HRRSStatsIter() :
ysr@777 972 _occupied(0),
ysr@777 973 _total_mem_sz(0),
ysr@777 974 _max_mem_sz(0),
ysr@777 975 _max_mem_sz_region(NULL)
ysr@777 976 {}
ysr@777 977
ysr@777 978 bool doHeapRegion(HeapRegion* r) {
ysr@777 979 if (r->continuesHumongous()) return false;
ysr@777 980 size_t mem_sz = r->rem_set()->mem_size();
ysr@777 981 if (mem_sz > _max_mem_sz) {
ysr@777 982 _max_mem_sz = mem_sz;
ysr@777 983 _max_mem_sz_region = r;
ysr@777 984 }
ysr@777 985 _total_mem_sz += mem_sz;
ysr@777 986 size_t occ = r->rem_set()->occupied();
ysr@777 987 _occupied += occ;
ysr@777 988 return false;
ysr@777 989 }
ysr@777 990 size_t total_mem_sz() { return _total_mem_sz; }
ysr@777 991 size_t max_mem_sz() { return _max_mem_sz; }
ysr@777 992 size_t occupied() { return _occupied; }
ysr@777 993 HeapRegion* max_mem_sz_region() { return _max_mem_sz_region; }
ysr@777 994 };
ysr@777 995
iveresov@1229 996 class PrintRSThreadVTimeClosure : public ThreadClosure {
iveresov@1229 997 public:
iveresov@1229 998 virtual void do_thread(Thread *t) {
iveresov@1229 999 ConcurrentG1RefineThread* crt = (ConcurrentG1RefineThread*) t;
iveresov@1229 1000 gclog_or_tty->print(" %5.2f", crt->vtime_accum());
iveresov@1229 1001 }
iveresov@1229 1002 };
iveresov@1229 1003
ysr@777 1004 void HRInto_G1RemSet::print_summary_info() {
ysr@777 1005 G1CollectedHeap* g1 = G1CollectedHeap::heap();
ysr@777 1006
ysr@777 1007 #if CARD_REPEAT_HISTO
ysr@777 1008 gclog_or_tty->print_cr("\nG1 card_repeat count histogram: ");
ysr@777 1009 gclog_or_tty->print_cr(" # of repeats --> # of cards with that number.");
ysr@777 1010 card_repeat_count.print_on(gclog_or_tty);
ysr@777 1011 #endif
ysr@777 1012
ysr@777 1013 if (FILTEROUTOFREGIONCLOSURE_DOHISTOGRAMCOUNT) {
ysr@777 1014 gclog_or_tty->print_cr("\nG1 rem-set out-of-region histogram: ");
ysr@777 1015 gclog_or_tty->print_cr(" # of CS ptrs --> # of cards with that number.");
ysr@777 1016 out_of_histo.print_on(gclog_or_tty);
ysr@777 1017 }
iveresov@1229 1018 gclog_or_tty->print_cr("\n Concurrent RS processed %d cards",
iveresov@1229 1019 _conc_refine_cards);
ysr@777 1020 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
ysr@777 1021 jint tot_processed_buffers =
ysr@777 1022 dcqs.processed_buffers_mut() + dcqs.processed_buffers_rs_thread();
ysr@777 1023 gclog_or_tty->print_cr(" Of %d completed buffers:", tot_processed_buffers);
iveresov@1229 1024 gclog_or_tty->print_cr(" %8d (%5.1f%%) by conc RS threads.",
ysr@777 1025 dcqs.processed_buffers_rs_thread(),
ysr@777 1026 100.0*(float)dcqs.processed_buffers_rs_thread()/
ysr@777 1027 (float)tot_processed_buffers);
ysr@777 1028 gclog_or_tty->print_cr(" %8d (%5.1f%%) by mutator threads.",
ysr@777 1029 dcqs.processed_buffers_mut(),
ysr@777 1030 100.0*(float)dcqs.processed_buffers_mut()/
ysr@777 1031 (float)tot_processed_buffers);
iveresov@1229 1032 gclog_or_tty->print_cr(" Conc RS threads times(s)");
iveresov@1229 1033 PrintRSThreadVTimeClosure p;
iveresov@1229 1034 gclog_or_tty->print(" ");
iveresov@1229 1035 g1->concurrent_g1_refine()->threads_do(&p);
ysr@777 1036 gclog_or_tty->print_cr("");
iveresov@1229 1037
ysr@777 1038 if (G1UseHRIntoRS) {
ysr@777 1039 HRRSStatsIter blk;
ysr@777 1040 g1->heap_region_iterate(&blk);
ysr@777 1041 gclog_or_tty->print_cr(" Total heap region rem set sizes = " SIZE_FORMAT "K."
ysr@777 1042 " Max = " SIZE_FORMAT "K.",
ysr@777 1043 blk.total_mem_sz()/K, blk.max_mem_sz()/K);
ysr@777 1044 gclog_or_tty->print_cr(" Static structures = " SIZE_FORMAT "K,"
ysr@777 1045 " free_lists = " SIZE_FORMAT "K.",
ysr@777 1046 HeapRegionRemSet::static_mem_size()/K,
ysr@777 1047 HeapRegionRemSet::fl_mem_size()/K);
ysr@777 1048 gclog_or_tty->print_cr(" %d occupied cards represented.",
ysr@777 1049 blk.occupied());
ysr@777 1050 gclog_or_tty->print_cr(" Max sz region = [" PTR_FORMAT ", " PTR_FORMAT " )"
apetrusenko@1112 1051 ", cap = " SIZE_FORMAT "K, occ = " SIZE_FORMAT "K.",
ysr@777 1052 blk.max_mem_sz_region()->bottom(), blk.max_mem_sz_region()->end(),
ysr@777 1053 (blk.max_mem_sz_region()->rem_set()->mem_size() + K - 1)/K,
ysr@777 1054 (blk.max_mem_sz_region()->rem_set()->occupied() + K - 1)/K);
ysr@777 1055 gclog_or_tty->print_cr(" Did %d coarsenings.",
ysr@777 1056 HeapRegionRemSet::n_coarsenings());
ysr@777 1057
ysr@777 1058 }
ysr@777 1059 }
johnc@2060 1060
ysr@777 1061 void HRInto_G1RemSet::prepare_for_verify() {
iveresov@1072 1062 if (G1HRRSFlushLogBuffersOnVerify &&
iveresov@1072 1063 (VerifyBeforeGC || VerifyAfterGC)
iveresov@1072 1064 && !_g1->full_collection()) {
ysr@777 1065 cleanupHRRS();
ysr@777 1066 _g1->set_refine_cte_cl_concurrency(false);
ysr@777 1067 if (SafepointSynchronize::is_at_safepoint()) {
ysr@777 1068 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
ysr@777 1069 dcqs.concatenate_logs();
ysr@777 1070 }
ysr@777 1071 bool cg1r_use_cache = _cg1r->use_cache();
ysr@777 1072 _cg1r->set_use_cache(false);
johnc@2060 1073 DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
johnc@2060 1074 updateRS(&into_cset_dcq, 0);
johnc@2060 1075 _g1->into_cset_dirty_card_queue_set().clear();
ysr@777 1076 _cg1r->set_use_cache(cg1r_use_cache);
iveresov@1072 1077
iveresov@1072 1078 assert(JavaThread::dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed");
ysr@777 1079 }
ysr@777 1080 }

mercurial