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

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

author
tschatzl
date
Fri, 10 Oct 2014 15:51:58 +0200
changeset 7257
e7d0505c8a30
parent 7218
6948da6d7c13
child 7535
7ae4e26cb1e0
child 7647
80ac3ee51955
child 7971
b554c7fa9478
permissions
-rw-r--r--

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

ysr@777 1 /*
drchase@6680 2 * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
ysr@777 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ysr@777 4 *
ysr@777 5 * This code is free software; you can redistribute it and/or modify it
ysr@777 6 * under the terms of the GNU General Public License version 2 only, as
ysr@777 7 * published by the Free Software Foundation.
ysr@777 8 *
ysr@777 9 * This code is distributed in the hope that it will be useful, but WITHOUT
ysr@777 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ysr@777 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ysr@777 12 * version 2 for more details (a copy is included in the LICENSE file that
ysr@777 13 * accompanied this code).
ysr@777 14 *
ysr@777 15 * You should have received a copy of the GNU General Public License version
ysr@777 16 * 2 along with this work; if not, write to the Free Software Foundation,
ysr@777 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ysr@777 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
ysr@777 22 *
ysr@777 23 */
ysr@777 24
stefank@2314 25 #include "precompiled.hpp"
stefank@2314 26 #include "gc_implementation/g1/concurrentG1Refine.hpp"
stefank@2314 27 #include "gc_implementation/g1/concurrentG1RefineThread.hpp"
stefank@2314 28 #include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
stefank@2314 29 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
stefank@2314 30 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
johnc@5078 31 #include "gc_implementation/g1/g1HotCardCache.hpp"
brutisso@3923 32 #include "gc_implementation/g1/g1GCPhaseTimes.hpp"
stefank@2314 33 #include "gc_implementation/g1/g1OopClosures.inline.hpp"
stefank@2314 34 #include "gc_implementation/g1/g1RemSet.inline.hpp"
tschatzl@7091 35 #include "gc_implementation/g1/heapRegionManager.inline.hpp"
tschatzl@5204 36 #include "gc_implementation/g1/heapRegionRemSet.hpp"
stefank@2314 37 #include "memory/iterator.hpp"
stefank@2314 38 #include "oops/oop.inline.hpp"
stefank@2314 39 #include "utilities/intHisto.hpp"
ysr@777 40
drchase@6680 41 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
drchase@6680 42
ysr@777 43 #define CARD_REPEAT_HISTO 0
ysr@777 44
ysr@777 45 #if CARD_REPEAT_HISTO
ysr@777 46 static size_t ct_freq_sz;
ysr@777 47 static jbyte* ct_freq = NULL;
ysr@777 48
ysr@777 49 void init_ct_freq_table(size_t heap_sz_bytes) {
ysr@777 50 if (ct_freq == NULL) {
ysr@777 51 ct_freq_sz = heap_sz_bytes/CardTableModRefBS::card_size;
ysr@777 52 ct_freq = new jbyte[ct_freq_sz];
ysr@777 53 for (size_t j = 0; j < ct_freq_sz; j++) ct_freq[j] = 0;
ysr@777 54 }
ysr@777 55 }
ysr@777 56
ysr@777 57 void ct_freq_note_card(size_t index) {
ysr@777 58 assert(0 <= index && index < ct_freq_sz, "Bounds error.");
ysr@777 59 if (ct_freq[index] < 100) { ct_freq[index]++; }
ysr@777 60 }
ysr@777 61
ysr@777 62 static IntHistogram card_repeat_count(10, 10);
ysr@777 63
ysr@777 64 void ct_freq_update_histo_and_reset() {
ysr@777 65 for (size_t j = 0; j < ct_freq_sz; j++) {
ysr@777 66 card_repeat_count.add_entry(ct_freq[j]);
ysr@777 67 ct_freq[j] = 0;
ysr@777 68 }
ysr@777 69
ysr@777 70 }
ysr@777 71 #endif
ysr@777 72
johnc@2216 73 G1RemSet::G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs)
johnc@2216 74 : _g1(g1), _conc_refine_cards(0),
johnc@2216 75 _ct_bs(ct_bs), _g1p(_g1->g1_policy()),
ysr@777 76 _cg1r(g1->concurrent_g1_refine()),
johnc@2060 77 _cset_rs_update_cl(NULL),
tschatzl@5204 78 _cards_scanned(NULL), _total_cards_scanned(0),
tschatzl@5204 79 _prev_period_summary()
ysr@777 80 {
ysr@777 81 _seq_task = new SubTasksDone(NumSeqTasks);
iveresov@1051 82 guarantee(n_workers() > 0, "There should be some workers");
zgu@3900 83 _cset_rs_update_cl = NEW_C_HEAP_ARRAY(OopsInHeapRegionClosure*, n_workers(), mtGC);
iveresov@1051 84 for (uint i = 0; i < n_workers(); i++) {
johnc@2060 85 _cset_rs_update_cl[i] = NULL;
iveresov@1051 86 }
tschatzl@5812 87 if (G1SummarizeRSetStats) {
tschatzl@5812 88 _prev_period_summary.initialize(this);
tschatzl@5812 89 }
ysr@777 90 }
ysr@777 91
johnc@2216 92 G1RemSet::~G1RemSet() {
ysr@777 93 delete _seq_task;
iveresov@1051 94 for (uint i = 0; i < n_workers(); i++) {
johnc@2060 95 assert(_cset_rs_update_cl[i] == NULL, "it should be");
iveresov@1051 96 }
zgu@3900 97 FREE_C_HEAP_ARRAY(OopsInHeapRegionClosure*, _cset_rs_update_cl, mtGC);
ysr@777 98 }
ysr@777 99
ysr@777 100 void CountNonCleanMemRegionClosure::do_MemRegion(MemRegion mr) {
ysr@777 101 if (_g1->is_in_g1_reserved(mr.start())) {
ysr@777 102 _n += (int) ((mr.byte_size() / CardTableModRefBS::card_size));
ysr@777 103 if (_start_first == NULL) _start_first = mr.start();
ysr@777 104 }
ysr@777 105 }
ysr@777 106
ysr@777 107 class ScanRSClosure : public HeapRegionClosure {
ysr@777 108 size_t _cards_done, _cards;
ysr@777 109 G1CollectedHeap* _g1h;
johnc@5548 110
ysr@777 111 OopsInHeapRegionClosure* _oc;
mgerdin@7208 112 CodeBlobClosure* _code_root_cl;
johnc@5548 113
ysr@777 114 G1BlockOffsetSharedArray* _bot_shared;
mgerdin@5811 115 G1SATBCardTableModRefBS *_ct_bs;
johnc@5548 116
johnc@5548 117 double _strong_code_root_scan_time_sec;
vkempik@6552 118 uint _worker_i;
johnc@5548 119 int _block_size;
johnc@5548 120 bool _try_claimed;
johnc@5548 121
ysr@777 122 public:
johnc@5548 123 ScanRSClosure(OopsInHeapRegionClosure* oc,
mgerdin@7208 124 CodeBlobClosure* code_root_cl,
vkempik@6552 125 uint worker_i) :
ysr@777 126 _oc(oc),
johnc@5548 127 _code_root_cl(code_root_cl),
johnc@5548 128 _strong_code_root_scan_time_sec(0.0),
ysr@777 129 _cards(0),
ysr@777 130 _cards_done(0),
ysr@777 131 _worker_i(worker_i),
ysr@777 132 _try_claimed(false)
ysr@777 133 {
ysr@777 134 _g1h = G1CollectedHeap::heap();
ysr@777 135 _bot_shared = _g1h->bot_shared();
mgerdin@5811 136 _ct_bs = _g1h->g1_barrier_set();
iveresov@1696 137 _block_size = MAX2<int>(G1RSetScanBlockSize, 1);
ysr@777 138 }
ysr@777 139
ysr@777 140 void set_try_claimed() { _try_claimed = true; }
ysr@777 141
ysr@777 142 void scanCard(size_t index, HeapRegion *r) {
johnc@3219 143 // Stack allocate the DirtyCardToOopClosure instance
johnc@3219 144 HeapRegionDCTOC cl(_g1h, r, _oc,
johnc@3219 145 CardTableModRefBS::Precise,
johnc@3219 146 HeapRegionDCTOC::IntoCSFilterKind);
ysr@777 147
ysr@777 148 // Set the "from" region in the closure.
ysr@777 149 _oc->set_region(r);
ysr@777 150 HeapWord* card_start = _bot_shared->address_for_index(index);
ysr@777 151 HeapWord* card_end = card_start + G1BlockOffsetSharedArray::N_words;
ysr@777 152 Space *sp = SharedHeap::heap()->space_containing(card_start);
tonyp@2849 153 MemRegion sm_region = sp->used_region_at_save_marks();
ysr@777 154 MemRegion mr = sm_region.intersection(MemRegion(card_start,card_end));
tonyp@2849 155 if (!mr.is_empty() && !_ct_bs->is_card_claimed(index)) {
tonyp@2849 156 // We make the card as "claimed" lazily (so races are possible
tonyp@2849 157 // but they're benign), which reduces the number of duplicate
tonyp@2849 158 // scans (the rsets of the regions in the cset can intersect).
tonyp@2849 159 _ct_bs->set_card_claimed(index);
tonyp@2849 160 _cards_done++;
johnc@3219 161 cl.do_MemRegion(mr);
ysr@777 162 }
ysr@777 163 }
ysr@777 164
ysr@777 165 void printCard(HeapRegion* card_region, size_t card_index,
ysr@777 166 HeapWord* card_start) {
vkempik@6552 167 gclog_or_tty->print_cr("T " UINT32_FORMAT " Region [" PTR_FORMAT ", " PTR_FORMAT ") "
ysr@777 168 "RS names card %p: "
ysr@777 169 "[" PTR_FORMAT ", " PTR_FORMAT ")",
ysr@777 170 _worker_i,
ysr@777 171 card_region->bottom(), card_region->end(),
ysr@777 172 card_index,
ysr@777 173 card_start, card_start + G1BlockOffsetSharedArray::N_words);
ysr@777 174 }
ysr@777 175
johnc@5548 176 void scan_strong_code_roots(HeapRegion* r) {
johnc@5548 177 double scan_start = os::elapsedTime();
johnc@5548 178 r->strong_code_roots_do(_code_root_cl);
johnc@5548 179 _strong_code_root_scan_time_sec += (os::elapsedTime() - scan_start);
johnc@5548 180 }
johnc@5548 181
ysr@777 182 bool doHeapRegion(HeapRegion* r) {
ysr@777 183 assert(r->in_collection_set(), "should only be called on elements of CS.");
ysr@777 184 HeapRegionRemSet* hrrs = r->rem_set();
ysr@777 185 if (hrrs->iter_is_complete()) return false; // All done.
ysr@777 186 if (!_try_claimed && !hrrs->claim_iter()) return false;
tonyp@2849 187 // If we ever free the collection set concurrently, we should also
tonyp@2849 188 // clear the card table concurrently therefore we won't need to
tonyp@2849 189 // add regions of the collection set to the dirty cards region.
apetrusenko@1231 190 _g1h->push_dirty_cards_region(r);
ysr@777 191 // If we didn't return above, then
ysr@777 192 // _try_claimed || r->claim_iter()
ysr@777 193 // is true: either we're supposed to work on claimed-but-not-complete
ysr@777 194 // regions, or we successfully claimed the region.
johnc@5548 195
johnc@5014 196 HeapRegionRemSetIterator iter(hrrs);
ysr@777 197 size_t card_index;
iveresov@1696 198
iveresov@1696 199 // We claim cards in block so as to recude the contention. The block size is determined by
iveresov@1696 200 // the G1RSetScanBlockSize parameter.
iveresov@1696 201 size_t jump_to_card = hrrs->iter_claimed_next(_block_size);
johnc@5014 202 for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
iveresov@1696 203 if (current_card >= jump_to_card + _block_size) {
iveresov@1696 204 jump_to_card = hrrs->iter_claimed_next(_block_size);
iveresov@1182 205 }
iveresov@1696 206 if (current_card < jump_to_card) continue;
ysr@777 207 HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index);
ysr@777 208 #if 0
ysr@777 209 gclog_or_tty->print("Rem set iteration yielded card [" PTR_FORMAT ", " PTR_FORMAT ").\n",
ysr@777 210 card_start, card_start + CardTableModRefBS::card_size_in_words);
ysr@777 211 #endif
ysr@777 212
ysr@777 213 HeapRegion* card_region = _g1h->heap_region_containing(card_start);
ysr@777 214 _cards++;
ysr@777 215
apetrusenko@1231 216 if (!card_region->is_on_dirty_cards_region_list()) {
apetrusenko@1231 217 _g1h->push_dirty_cards_region(card_region);
apetrusenko@1231 218 }
apetrusenko@1231 219
tonyp@2849 220 // If the card is dirty, then we will scan it during updateRS.
tonyp@2849 221 if (!card_region->in_collection_set() &&
tonyp@2849 222 !_ct_bs->is_card_dirty(card_index)) {
tonyp@2849 223 scanCard(card_index, card_region);
ysr@777 224 }
ysr@777 225 }
iveresov@1182 226 if (!_try_claimed) {
johnc@5548 227 // Scan the strong code root list attached to the current region
johnc@5548 228 scan_strong_code_roots(r);
johnc@5548 229
iveresov@1182 230 hrrs->set_iter_complete();
iveresov@1182 231 }
ysr@777 232 return false;
ysr@777 233 }
johnc@5548 234
johnc@5548 235 double strong_code_root_scan_time_sec() {
johnc@5548 236 return _strong_code_root_scan_time_sec;
johnc@5548 237 }
johnc@5548 238
ysr@777 239 size_t cards_done() { return _cards_done;}
ysr@777 240 size_t cards_looked_up() { return _cards;}
ysr@777 241 };
ysr@777 242
johnc@5548 243 void G1RemSet::scanRS(OopsInHeapRegionClosure* oc,
mgerdin@7208 244 CodeBlobClosure* code_root_cl,
vkempik@6552 245 uint worker_i) {
ysr@777 246 double rs_time_start = os::elapsedTime();
johnc@3296 247 HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i);
ysr@777 248
johnc@5548 249 ScanRSClosure scanRScl(oc, code_root_cl, worker_i);
johnc@3175 250
ysr@777 251 _g1->collection_set_iterate_from(startRegion, &scanRScl);
ysr@777 252 scanRScl.set_try_claimed();
ysr@777 253 _g1->collection_set_iterate_from(startRegion, &scanRScl);
ysr@777 254
johnc@5548 255 double scan_rs_time_sec = (os::elapsedTime() - rs_time_start)
johnc@5548 256 - scanRScl.strong_code_root_scan_time_sec();
ysr@777 257
johnc@5548 258 assert(_cards_scanned != NULL, "invariant");
ysr@777 259 _cards_scanned[worker_i] = scanRScl.cards_done();
ysr@777 260
brutisso@3923 261 _g1p->phase_times()->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
johnc@5548 262 _g1p->phase_times()->record_strong_code_root_scan_time(worker_i,
johnc@5548 263 scanRScl.strong_code_root_scan_time_sec() * 1000.0);
ysr@777 264 }
ysr@777 265
johnc@2060 266 // Closure used for updating RSets and recording references that
johnc@2060 267 // point into the collection set. Only called during an
johnc@2060 268 // evacuation pause.
ysr@777 269
johnc@2060 270 class RefineRecordRefsIntoCSCardTableEntryClosure: public CardTableEntryClosure {
johnc@2060 271 G1RemSet* _g1rs;
johnc@2060 272 DirtyCardQueue* _into_cset_dcq;
johnc@2060 273 public:
johnc@2060 274 RefineRecordRefsIntoCSCardTableEntryClosure(G1CollectedHeap* g1h,
johnc@2060 275 DirtyCardQueue* into_cset_dcq) :
johnc@2060 276 _g1rs(g1h->g1_rem_set()), _into_cset_dcq(into_cset_dcq)
johnc@2060 277 {}
vkempik@6552 278 bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
johnc@2060 279 // The only time we care about recording cards that
johnc@2060 280 // contain references that point into the collection set
johnc@2060 281 // is during RSet updating within an evacuation pause.
johnc@2060 282 // In this case worker_i should be the id of a GC worker thread.
johnc@2060 283 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
vkempik@6552 284 assert(worker_i < (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker");
johnc@2060 285
johnc@5078 286 if (_g1rs->refine_card(card_ptr, worker_i, true)) {
johnc@2060 287 // 'card_ptr' contains references that point into the collection
johnc@2060 288 // set. We need to record the card in the DCQS
johnc@2060 289 // (G1CollectedHeap::into_cset_dirty_card_queue_set())
johnc@2060 290 // that's used for that purpose.
johnc@2060 291 //
johnc@2060 292 // Enqueue the card
johnc@2060 293 _into_cset_dcq->enqueue(card_ptr);
johnc@2060 294 }
johnc@2060 295 return true;
johnc@2060 296 }
johnc@2060 297 };
johnc@2060 298
vkempik@6552 299 void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) {
ysr@777 300 double start = os::elapsedTime();
johnc@2060 301 // Apply the given closure to all remaining log entries.
johnc@2060 302 RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
johnc@3175 303
johnc@2060 304 _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i);
johnc@2060 305
iveresov@1229 306 // Now there should be no dirty cards.
iveresov@1229 307 if (G1RSLogCheckCardTable) {
iveresov@1229 308 CountNonCleanMemRegionClosure cl(_g1);
iveresov@1229 309 _ct_bs->mod_card_iterate(&cl);
iveresov@1229 310 // XXX This isn't true any more: keeping cards of young regions
iveresov@1229 311 // marked dirty broke it. Need some reasonable fix.
iveresov@1229 312 guarantee(cl.n() == 0, "Card table should be clean.");
ysr@777 313 }
iveresov@1229 314
brutisso@3923 315 _g1p->phase_times()->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0);
ysr@777 316 }
ysr@777 317
johnc@2216 318 void G1RemSet::cleanupHRRS() {
ysr@777 319 HeapRegionRemSet::cleanup();
ysr@777 320 }
ysr@777 321
johnc@2216 322 void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
mgerdin@7208 323 CodeBlobClosure* code_root_cl,
vkempik@6552 324 uint worker_i) {
ysr@777 325 #if CARD_REPEAT_HISTO
ysr@777 326 ct_freq_update_histo_and_reset();
ysr@777 327 #endif
ysr@777 328
johnc@2060 329 // We cache the value of 'oc' closure into the appropriate slot in the
johnc@2060 330 // _cset_rs_update_cl for this worker
vkempik@6552 331 assert(worker_i < n_workers(), "sanity");
johnc@2060 332 _cset_rs_update_cl[worker_i] = oc;
johnc@2060 333
johnc@2060 334 // A DirtyCardQueue that is used to hold cards containing references
johnc@2060 335 // that point into the collection set. This DCQ is associated with a
johnc@2060 336 // special DirtyCardQueueSet (see g1CollectedHeap.hpp). Under normal
johnc@2060 337 // circumstances (i.e. the pause successfully completes), these cards
johnc@2060 338 // are just discarded (there's no need to update the RSets of regions
johnc@2060 339 // that were in the collection set - after the pause these regions
johnc@2060 340 // are wholly 'free' of live objects. In the event of an evacuation
tschatzl@7218 341 // failure the cards/buffers in this queue set are passed to the
tschatzl@7218 342 // DirtyCardQueueSet that is used to manage RSet updates
johnc@2060 343 DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
johnc@2060 344
johnc@2063 345 assert((ParallelGCThreads > 0) || worker_i == 0, "invariant");
johnc@2063 346
johnc@2063 347 // The two flags below were introduced temporarily to serialize
johnc@2063 348 // the updating and scanning of remembered sets. There are some
johnc@2063 349 // race conditions when these two operations are done in parallel
johnc@2063 350 // and they are causing failures. When we resolve said race
johnc@2063 351 // conditions, we'll revert back to parallel remembered set
johnc@2063 352 // updating and scanning. See CRs 6677707 and 6677708.
johnc@2063 353 if (G1UseParallelRSetUpdating || (worker_i == 0)) {
johnc@2063 354 updateRS(&into_cset_dcq, worker_i);
ysr@777 355 } else {
brutisso@4015 356 _g1p->phase_times()->record_update_rs_processed_buffers(worker_i, 0);
brutisso@3923 357 _g1p->phase_times()->record_update_rs_time(worker_i, 0.0);
johnc@2063 358 }
johnc@2063 359 if (G1UseParallelRSetScanning || (worker_i == 0)) {
johnc@5548 360 scanRS(oc, code_root_cl, worker_i);
johnc@2063 361 } else {
brutisso@3923 362 _g1p->phase_times()->record_scan_rs_time(worker_i, 0.0);
ysr@777 363 }
johnc@2060 364
johnc@2060 365 // We now clear the cached values of _cset_rs_update_cl for this worker
johnc@2060 366 _cset_rs_update_cl[worker_i] = NULL;
ysr@777 367 }
ysr@777 368
johnc@2216 369 void G1RemSet::prepare_for_oops_into_collection_set_do() {
ysr@777 370 cleanupHRRS();
ysr@777 371 _g1->set_refine_cte_cl_concurrency(false);
ysr@777 372 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
ysr@777 373 dcqs.concatenate_logs();
ysr@777 374
ysr@777 375 guarantee( _cards_scanned == NULL, "invariant" );
zgu@3900 376 _cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers(), mtGC);
apetrusenko@980 377 for (uint i = 0; i < n_workers(); ++i) {
apetrusenko@980 378 _cards_scanned[i] = 0;
apetrusenko@980 379 }
ysr@777 380 _total_cards_scanned = 0;
ysr@777 381 }
ysr@777 382
johnc@2216 383 void G1RemSet::cleanup_after_oops_into_collection_set_do() {
ysr@777 384 guarantee( _cards_scanned != NULL, "invariant" );
ysr@777 385 _total_cards_scanned = 0;
tonyp@2974 386 for (uint i = 0; i < n_workers(); ++i) {
ysr@777 387 _total_cards_scanned += _cards_scanned[i];
tonyp@2974 388 }
zgu@3900 389 FREE_C_HEAP_ARRAY(size_t, _cards_scanned, mtGC);
ysr@777 390 _cards_scanned = NULL;
ysr@777 391 // Cleanup after copy
ysr@777 392 _g1->set_refine_cte_cl_concurrency(true);
ysr@777 393 // Set all cards back to clean.
ysr@777 394 _g1->cleanUpCardTable();
iveresov@1229 395
johnc@2060 396 DirtyCardQueueSet& into_cset_dcqs = _g1->into_cset_dirty_card_queue_set();
johnc@2060 397 int into_cset_n_buffers = into_cset_dcqs.completed_buffers_num();
johnc@2060 398
iveresov@1051 399 if (_g1->evacuation_failed()) {
tschatzl@6406 400 double restore_remembered_set_start = os::elapsedTime();
tschatzl@6406 401
johnc@2060 402 // Restore remembered sets for the regions pointing into the collection set.
tschatzl@7218 403 // We just need to transfer the completed buffers from the DirtyCardQueueSet
tschatzl@7218 404 // used to hold cards that contain references that point into the collection set
tschatzl@7218 405 // to the DCQS used to hold the deferred RS updates.
tschatzl@7218 406 _g1->dirty_card_queue_set().merge_bufferlists(&into_cset_dcqs);
tschatzl@6406 407 _g1->g1_policy()->phase_times()->record_evac_fail_restore_remsets((os::elapsedTime() - restore_remembered_set_start) * 1000.0);
iveresov@1051 408 }
johnc@2060 409
johnc@2060 410 // Free any completed buffers in the DirtyCardQueueSet used to hold cards
johnc@2060 411 // which contain references that point into the collection.
johnc@2060 412 _g1->into_cset_dirty_card_queue_set().clear();
johnc@2060 413 assert(_g1->into_cset_dirty_card_queue_set().completed_buffers_num() == 0,
johnc@2060 414 "all buffers should be freed");
johnc@2060 415 _g1->into_cset_dirty_card_queue_set().clear_n_completed_buffers();
ysr@777 416 }
ysr@777 417
ysr@777 418 class ScrubRSClosure: public HeapRegionClosure {
ysr@777 419 G1CollectedHeap* _g1h;
ysr@777 420 BitMap* _region_bm;
ysr@777 421 BitMap* _card_bm;
ysr@777 422 CardTableModRefBS* _ctbs;
ysr@777 423 public:
ysr@777 424 ScrubRSClosure(BitMap* region_bm, BitMap* card_bm) :
ysr@777 425 _g1h(G1CollectedHeap::heap()),
ysr@777 426 _region_bm(region_bm), _card_bm(card_bm),
mgerdin@5811 427 _ctbs(_g1h->g1_barrier_set()) {}
ysr@777 428
ysr@777 429 bool doHeapRegion(HeapRegion* r) {
ysr@777 430 if (!r->continuesHumongous()) {
ysr@777 431 r->rem_set()->scrub(_ctbs, _region_bm, _card_bm);
ysr@777 432 }
ysr@777 433 return false;
ysr@777 434 }
ysr@777 435 };
ysr@777 436
johnc@2216 437 void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm) {
ysr@777 438 ScrubRSClosure scrub_cl(region_bm, card_bm);
ysr@777 439 _g1->heap_region_iterate(&scrub_cl);
ysr@777 440 }
ysr@777 441
johnc@2216 442 void G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm,
jmasa@3357 443 uint worker_num, int claim_val) {
ysr@777 444 ScrubRSClosure scrub_cl(region_bm, card_bm);
jmasa@3294 445 _g1->heap_region_par_iterate_chunked(&scrub_cl,
jmasa@3294 446 worker_num,
jmasa@3357 447 n_workers(),
jmasa@3294 448 claim_val);
ysr@777 449 }
ysr@777 450
johnc@3466 451 G1TriggerClosure::G1TriggerClosure() :
johnc@3466 452 _triggered(false) { }
johnc@2060 453
johnc@3466 454 G1InvokeIfNotTriggeredClosure::G1InvokeIfNotTriggeredClosure(G1TriggerClosure* t_cl,
johnc@3466 455 OopClosure* oop_cl) :
johnc@3466 456 _trigger_cl(t_cl), _oop_cl(oop_cl) { }
johnc@3466 457
johnc@3466 458 G1Mux2Closure::G1Mux2Closure(OopClosure *c1, OopClosure *c2) :
johnc@3466 459 _c1(c1), _c2(c2) { }
johnc@3466 460
johnc@3466 461 G1UpdateRSOrPushRefOopClosure::
johnc@3466 462 G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h,
johnc@3466 463 G1RemSet* rs,
johnc@3466 464 OopsInHeapRegionClosure* push_ref_cl,
johnc@3466 465 bool record_refs_into_cset,
vkempik@6552 466 uint worker_i) :
johnc@3466 467 _g1(g1h), _g1_rem_set(rs), _from(NULL),
johnc@3466 468 _record_refs_into_cset(record_refs_into_cset),
johnc@3466 469 _push_ref_cl(push_ref_cl), _worker_i(worker_i) { }
johnc@2060 470
johnc@5078 471 // Returns true if the given card contains references that point
johnc@5078 472 // into the collection set, if we're checking for such references;
johnc@5078 473 // false otherwise.
johnc@5078 474
vkempik@6552 475 bool G1RemSet::refine_card(jbyte* card_ptr, uint worker_i,
johnc@5078 476 bool check_for_refs_into_cset) {
tschatzl@7051 477 assert(_g1->is_in_exact(_ct_bs->addr_for(card_ptr)),
tschatzl@7051 478 err_msg("Card at "PTR_FORMAT" index "SIZE_FORMAT" representing heap at "PTR_FORMAT" (%u) must be in committed heap",
tschatzl@7051 479 p2i(card_ptr),
tschatzl@7051 480 _ct_bs->index_for(_ct_bs->addr_for(card_ptr)),
tschatzl@7051 481 _ct_bs->addr_for(card_ptr),
tschatzl@7051 482 _g1->addr_to_region(_ct_bs->addr_for(card_ptr))));
johnc@5078 483
johnc@5078 484 // If the card is no longer dirty, nothing to do.
johnc@5078 485 if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
johnc@5078 486 // No need to return that this card contains refs that point
johnc@5078 487 // into the collection set.
johnc@5078 488 return false;
johnc@5078 489 }
johnc@5078 490
johnc@1325 491 // Construct the region representing the card.
johnc@1325 492 HeapWord* start = _ct_bs->addr_for(card_ptr);
johnc@1325 493 // And find the region containing it.
johnc@1325 494 HeapRegion* r = _g1->heap_region_containing(start);
johnc@5078 495
johnc@5078 496 // Why do we have to check here whether a card is on a young region,
johnc@5078 497 // given that we dirty young regions and, as a result, the
johnc@5078 498 // post-barrier is supposed to filter them out and never to enqueue
johnc@5078 499 // them? When we allocate a new region as the "allocation region" we
johnc@5078 500 // actually dirty its cards after we release the lock, since card
johnc@5078 501 // dirtying while holding the lock was a performance bottleneck. So,
johnc@5078 502 // as a result, it is possible for other threads to actually
johnc@5078 503 // allocate objects in the region (after the acquire the lock)
johnc@5078 504 // before all the cards on the region are dirtied. This is unlikely,
johnc@5078 505 // and it doesn't happen often, but it can happen. So, the extra
johnc@5078 506 // check below filters out those cards.
johnc@5078 507 if (r->is_young()) {
johnc@5078 508 return false;
johnc@5078 509 }
johnc@5078 510
johnc@5078 511 // While we are processing RSet buffers during the collection, we
johnc@5078 512 // actually don't want to scan any cards on the collection set,
johnc@5078 513 // since we don't want to update remebered sets with entries that
johnc@5078 514 // point into the collection set, given that live objects from the
johnc@5078 515 // collection set are about to move and such entries will be stale
johnc@5078 516 // very soon. This change also deals with a reliability issue which
johnc@5078 517 // involves scanning a card in the collection set and coming across
johnc@5078 518 // an array that was being chunked and looking malformed. Note,
johnc@5078 519 // however, that if evacuation fails, we have to scan any objects
johnc@5078 520 // that were not moved and create any missing entries.
johnc@5078 521 if (r->in_collection_set()) {
johnc@5078 522 return false;
johnc@5078 523 }
johnc@5078 524
johnc@5078 525 // The result from the hot card cache insert call is either:
johnc@5078 526 // * pointer to the current card
johnc@5078 527 // (implying that the current card is not 'hot'),
johnc@5078 528 // * null
johnc@5078 529 // (meaning we had inserted the card ptr into the "hot" card cache,
johnc@5078 530 // which had some headroom),
johnc@5078 531 // * a pointer to a "hot" card that was evicted from the "hot" cache.
johnc@5078 532 //
johnc@5078 533
johnc@5078 534 G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
johnc@5078 535 if (hot_card_cache->use_cache()) {
johnc@5078 536 assert(!check_for_refs_into_cset, "sanity");
johnc@5078 537 assert(!SafepointSynchronize::is_at_safepoint(), "sanity");
johnc@5078 538
johnc@5078 539 card_ptr = hot_card_cache->insert(card_ptr);
johnc@5078 540 if (card_ptr == NULL) {
johnc@5078 541 // There was no eviction. Nothing to do.
johnc@5078 542 return false;
johnc@5078 543 }
johnc@5078 544
johnc@5078 545 start = _ct_bs->addr_for(card_ptr);
johnc@5078 546 r = _g1->heap_region_containing(start);
johnc@5078 547
johnc@5078 548 // Checking whether the region we got back from the cache
johnc@5078 549 // is young here is inappropriate. The region could have been
johnc@5078 550 // freed, reallocated and tagged as young while in the cache.
johnc@5078 551 // Hence we could see its young type change at any time.
johnc@5078 552 }
johnc@1325 553
coleenp@4037 554 // Don't use addr_for(card_ptr + 1) which can ask for
coleenp@4037 555 // a card beyond the heap. This is not safe without a perm
coleenp@4037 556 // gen at the upper end of the heap.
coleenp@4037 557 HeapWord* end = start + CardTableModRefBS::card_size_in_words;
johnc@1325 558 MemRegion dirtyRegion(start, end);
johnc@1325 559
johnc@1325 560 #if CARD_REPEAT_HISTO
johnc@2504 561 init_ct_freq_table(_g1->max_capacity());
johnc@1325 562 ct_freq_note_card(_ct_bs->index_for(start));
johnc@1325 563 #endif
johnc@1325 564
brutisso@3267 565 OopsInHeapRegionClosure* oops_in_heap_closure = NULL;
brutisso@3267 566 if (check_for_refs_into_cset) {
brutisso@3267 567 // ConcurrentG1RefineThreads have worker numbers larger than what
brutisso@3267 568 // _cset_rs_update_cl[] is set up to handle. But those threads should
brutisso@3267 569 // only be active outside of a collection which means that when they
brutisso@3267 570 // reach here they should have check_for_refs_into_cset == false.
brutisso@3267 571 assert((size_t)worker_i < n_workers(), "index of worker larger than _cset_rs_update_cl[].length");
brutisso@3267 572 oops_in_heap_closure = _cset_rs_update_cl[worker_i];
brutisso@3267 573 }
johnc@3466 574 G1UpdateRSOrPushRefOopClosure update_rs_oop_cl(_g1,
johnc@3466 575 _g1->g1_rem_set(),
johnc@3466 576 oops_in_heap_closure,
johnc@3466 577 check_for_refs_into_cset,
johnc@3466 578 worker_i);
johnc@1325 579 update_rs_oop_cl.set_from(r);
johnc@2060 580
johnc@3466 581 G1TriggerClosure trigger_cl;
johnc@3179 582 FilterIntoCSClosure into_cs_cl(NULL, _g1, &trigger_cl);
johnc@3466 583 G1InvokeIfNotTriggeredClosure invoke_cl(&trigger_cl, &into_cs_cl);
johnc@3466 584 G1Mux2Closure mux(&invoke_cl, &update_rs_oop_cl);
johnc@2060 585
johnc@2060 586 FilterOutOfRegionClosure filter_then_update_rs_oop_cl(r,
johnc@2060 587 (check_for_refs_into_cset ?
johnc@2060 588 (OopClosure*)&mux :
johnc@2060 589 (OopClosure*)&update_rs_oop_cl));
johnc@1325 590
johnc@2021 591 // The region for the current card may be a young region. The
johnc@2021 592 // current card may have been a card that was evicted from the
johnc@2021 593 // card cache. When the card was inserted into the cache, we had
johnc@2021 594 // determined that its region was non-young. While in the cache,
johnc@2021 595 // the region may have been freed during a cleanup pause, reallocated
johnc@2021 596 // and tagged as young.
johnc@2021 597 //
johnc@2021 598 // We wish to filter out cards for such a region but the current
tonyp@2849 599 // thread, if we're running concurrently, may "see" the young type
johnc@2021 600 // change at any time (so an earlier "is_young" check may pass or
johnc@2021 601 // fail arbitrarily). We tell the iteration code to perform this
johnc@2021 602 // filtering when it has been determined that there has been an actual
johnc@2021 603 // allocation in this region and making it safe to check the young type.
johnc@2021 604 bool filter_young = true;
johnc@2021 605
johnc@1325 606 HeapWord* stop_point =
johnc@1325 607 r->oops_on_card_seq_iterate_careful(dirtyRegion,
johnc@2021 608 &filter_then_update_rs_oop_cl,
tonyp@2849 609 filter_young,
tonyp@2849 610 card_ptr);
johnc@2021 611
johnc@1325 612 // If stop_point is non-null, then we encountered an unallocated region
johnc@1325 613 // (perhaps the unfilled portion of a TLAB.) For now, we'll dirty the
johnc@1325 614 // card and re-enqueue: if we put off the card until a GC pause, then the
johnc@1325 615 // unallocated portion will be filled in. Alternatively, we might try
johnc@1325 616 // the full complexity of the technique used in "regular" precleaning.
johnc@1325 617 if (stop_point != NULL) {
johnc@1325 618 // The card might have gotten re-dirtied and re-enqueued while we
johnc@1325 619 // worked. (In fact, it's pretty likely.)
johnc@1325 620 if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
johnc@1325 621 *card_ptr = CardTableModRefBS::dirty_card_val();
johnc@1325 622 MutexLockerEx x(Shared_DirtyCardQ_lock,
johnc@1325 623 Mutex::_no_safepoint_check_flag);
johnc@1325 624 DirtyCardQueue* sdcq =
johnc@1325 625 JavaThread::dirty_card_queue_set().shared_dirty_card_queue();
johnc@1325 626 sdcq->enqueue(card_ptr);
johnc@1325 627 }
johnc@1325 628 } else {
johnc@1325 629 _conc_refine_cards++;
johnc@1325 630 }
johnc@2060 631
johnc@5078 632 // This gets set to true if the card being refined has
johnc@5078 633 // references that point into the collection set.
johnc@5078 634 bool has_refs_into_cset = trigger_cl.triggered();
johnc@1325 635
johnc@5078 636 // We should only be detecting that the card contains references
johnc@5078 637 // that point into the collection set if the current thread is
johnc@5078 638 // a GC worker thread.
johnc@5078 639 assert(!has_refs_into_cset || SafepointSynchronize::is_at_safepoint(),
johnc@5078 640 "invalid result at non safepoint");
ysr@777 641
johnc@5078 642 return has_refs_into_cset;
ysr@777 643 }
ysr@777 644
tschatzl@5807 645 void G1RemSet::print_periodic_summary_info(const char* header) {
tschatzl@5204 646 G1RemSetSummary current;
tschatzl@5812 647 current.initialize(this);
ysr@777 648
tschatzl@5204 649 _prev_period_summary.subtract_from(&current);
tschatzl@5807 650 print_summary_info(&_prev_period_summary, header);
ysr@777 651
tschatzl@5204 652 _prev_period_summary.set(&current);
tschatzl@5204 653 }
iveresov@1229 654
johnc@2216 655 void G1RemSet::print_summary_info() {
tschatzl@5204 656 G1RemSetSummary current;
tschatzl@5812 657 current.initialize(this);
tschatzl@5204 658
tschatzl@5204 659 print_summary_info(&current, " Cumulative RS summary");
tschatzl@5204 660 }
tschatzl@5204 661
tschatzl@5204 662 void G1RemSet::print_summary_info(G1RemSetSummary * summary, const char * header) {
tschatzl@5204 663 assert(summary != NULL, "just checking");
tschatzl@5204 664
tschatzl@5204 665 if (header != NULL) {
tschatzl@5204 666 gclog_or_tty->print_cr("%s", header);
tschatzl@5204 667 }
ysr@777 668
ysr@777 669 #if CARD_REPEAT_HISTO
ysr@777 670 gclog_or_tty->print_cr("\nG1 card_repeat count histogram: ");
ysr@777 671 gclog_or_tty->print_cr(" # of repeats --> # of cards with that number.");
ysr@777 672 card_repeat_count.print_on(gclog_or_tty);
ysr@777 673 #endif
ysr@777 674
tschatzl@5204 675 summary->print_on(gclog_or_tty);
ysr@777 676 }
johnc@2060 677
johnc@2216 678 void G1RemSet::prepare_for_verify() {
iveresov@1072 679 if (G1HRRSFlushLogBuffersOnVerify &&
iveresov@1072 680 (VerifyBeforeGC || VerifyAfterGC)
johnc@5205 681 && (!_g1->full_collection() || G1VerifyRSetsDuringFullGC)) {
ysr@777 682 cleanupHRRS();
ysr@777 683 _g1->set_refine_cte_cl_concurrency(false);
ysr@777 684 if (SafepointSynchronize::is_at_safepoint()) {
ysr@777 685 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
ysr@777 686 dcqs.concatenate_logs();
ysr@777 687 }
johnc@5078 688
johnc@5078 689 G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
johnc@5078 690 bool use_hot_card_cache = hot_card_cache->use_cache();
johnc@5078 691 hot_card_cache->set_use_cache(false);
johnc@5078 692
johnc@2060 693 DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
johnc@2060 694 updateRS(&into_cset_dcq, 0);
johnc@2060 695 _g1->into_cset_dirty_card_queue_set().clear();
iveresov@1072 696
johnc@5078 697 hot_card_cache->set_use_cache(use_hot_card_cache);
iveresov@1072 698 assert(JavaThread::dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed");
ysr@777 699 }
ysr@777 700 }

mercurial