63 static IntHistogram card_repeat_count(10, 10);
64
65 void ct_freq_update_histo_and_reset() {
66 for (size_t j = 0; j < ct_freq_sz; j++) {
67 card_repeat_count.add_entry(ct_freq[j]);
68 ct_freq[j] = 0;
69 }
70
71 }
72 #endif
73
74 G1RemSet::G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs)
75 : _g1(g1), _conc_refine_cards(0),
76 _ct_bs(ct_bs), _g1p(_g1->g1_policy()),
77 _cg1r(g1->concurrent_g1_refine()),
78 _cset_rs_update_cl(NULL),
79 _cards_scanned(NULL), _total_cards_scanned(0),
80 _prev_period_summary()
81 {
82 _seq_task = new SubTasksDone(NumSeqTasks);
83 guarantee(n_workers() > 0, "There should be some workers");
84 _cset_rs_update_cl = NEW_C_HEAP_ARRAY(OopsInHeapRegionClosure*, n_workers(), mtGC);
85 for (uint i = 0; i < n_workers(); i++) {
86 _cset_rs_update_cl[i] = NULL;
87 }
88 if (G1SummarizeRSetStats) {
89 _prev_period_summary.initialize(this);
90 }
91 }
92
93 G1RemSet::~G1RemSet() {
94 delete _seq_task;
95 for (uint i = 0; i < n_workers(); i++) {
96 assert(_cset_rs_update_cl[i] == NULL, "it should be");
97 }
98 FREE_C_HEAP_ARRAY(OopsInHeapRegionClosure*, _cset_rs_update_cl, mtGC);
99 }
100
101 void CountNonCleanMemRegionClosure::do_MemRegion(MemRegion mr) {
102 if (_g1->is_in_g1_reserved(mr.start())) {
103 _n += (int) ((mr.byte_size() / CardTableModRefBS::card_size));
265 }
266
267 // Closure used for updating RSets and recording references that
268 // point into the collection set. Only called during an
269 // evacuation pause.
270
271 class RefineRecordRefsIntoCSCardTableEntryClosure: public CardTableEntryClosure {
272 G1RemSet* _g1rs;
273 DirtyCardQueue* _into_cset_dcq;
274 public:
275 RefineRecordRefsIntoCSCardTableEntryClosure(G1CollectedHeap* g1h,
276 DirtyCardQueue* into_cset_dcq) :
277 _g1rs(g1h->g1_rem_set()), _into_cset_dcq(into_cset_dcq)
278 {}
279 bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
280 // The only time we care about recording cards that
281 // contain references that point into the collection set
282 // is during RSet updating within an evacuation pause.
283 // In this case worker_i should be the id of a GC worker thread.
284 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
285 assert(worker_i < (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker");
286
287 if (_g1rs->refine_card(card_ptr, worker_i, true)) {
288 // 'card_ptr' contains references that point into the collection
289 // set. We need to record the card in the DCQS
290 // (G1CollectedHeap::into_cset_dirty_card_queue_set())
291 // that's used for that purpose.
292 //
293 // Enqueue the card
294 _into_cset_dcq->enqueue(card_ptr);
295 }
296 return true;
297 }
298 };
299
300 void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) {
301 double start = os::elapsedTime();
302 // Apply the given closure to all remaining log entries.
303 RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
304
305 _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i);
326 #if CARD_REPEAT_HISTO
327 ct_freq_update_histo_and_reset();
328 #endif
329
330 // We cache the value of 'oc' closure into the appropriate slot in the
331 // _cset_rs_update_cl for this worker
332 assert(worker_i < n_workers(), "sanity");
333 _cset_rs_update_cl[worker_i] = oc;
334
335 // A DirtyCardQueue that is used to hold cards containing references
336 // that point into the collection set. This DCQ is associated with a
337 // special DirtyCardQueueSet (see g1CollectedHeap.hpp). Under normal
338 // circumstances (i.e. the pause successfully completes), these cards
339 // are just discarded (there's no need to update the RSets of regions
340 // that were in the collection set - after the pause these regions
341 // are wholly 'free' of live objects. In the event of an evacuation
342 // failure the cards/buffers in this queue set are passed to the
343 // DirtyCardQueueSet that is used to manage RSet updates
344 DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
345
346 assert((ParallelGCThreads > 0) || worker_i == 0, "invariant");
347
348 updateRS(&into_cset_dcq, worker_i);
349 scanRS(oc, code_root_cl, worker_i);
350
351 // We now clear the cached values of _cset_rs_update_cl for this worker
352 _cset_rs_update_cl[worker_i] = NULL;
353 }
354
355 void G1RemSet::prepare_for_oops_into_collection_set_do() {
356 cleanupHRRS();
357 _g1->set_refine_cte_cl_concurrency(false);
358 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
359 dcqs.concatenate_logs();
360
361 guarantee( _cards_scanned == NULL, "invariant" );
362 _cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers(), mtGC);
363 for (uint i = 0; i < n_workers(); ++i) {
364 _cards_scanned[i] = 0;
365 }
366 _total_cards_scanned = 0;
367 }
403
404 class ScrubRSClosure: public HeapRegionClosure {
405 G1CollectedHeap* _g1h;
406 BitMap* _region_bm;
407 BitMap* _card_bm;
408 CardTableModRefBS* _ctbs;
409 public:
410 ScrubRSClosure(BitMap* region_bm, BitMap* card_bm) :
411 _g1h(G1CollectedHeap::heap()),
412 _region_bm(region_bm), _card_bm(card_bm),
413 _ctbs(_g1h->g1_barrier_set()) {}
414
415 bool doHeapRegion(HeapRegion* r) {
416 if (!r->is_continues_humongous()) {
417 r->rem_set()->scrub(_ctbs, _region_bm, _card_bm);
418 }
419 return false;
420 }
421 };
422
423 void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm) {
424 ScrubRSClosure scrub_cl(region_bm, card_bm);
425 _g1->heap_region_iterate(&scrub_cl);
426 }
427
428 void G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer *hrclaimer) {
429 ScrubRSClosure scrub_cl(region_bm, card_bm);
430 _g1->heap_region_par_iterate(&scrub_cl, worker_num, hrclaimer);
431 }
432
433 G1TriggerClosure::G1TriggerClosure() :
434 _triggered(false) { }
435
436 G1InvokeIfNotTriggeredClosure::G1InvokeIfNotTriggeredClosure(G1TriggerClosure* t_cl,
437 OopClosure* oop_cl) :
438 _trigger_cl(t_cl), _oop_cl(oop_cl) { }
439
440 G1Mux2Closure::G1Mux2Closure(OopClosure *c1, OopClosure *c2) :
441 _c1(c1), _c2(c2) { }
442
443 G1UpdateRSOrPushRefOopClosure::
444 G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h,
445 G1RemSet* rs,
446 OopsInHeapRegionClosure* push_ref_cl,
447 bool record_refs_into_cset,
448 uint worker_i) :
|
63 static IntHistogram card_repeat_count(10, 10);
64
65 void ct_freq_update_histo_and_reset() {
66 for (size_t j = 0; j < ct_freq_sz; j++) {
67 card_repeat_count.add_entry(ct_freq[j]);
68 ct_freq[j] = 0;
69 }
70
71 }
72 #endif
73
74 G1RemSet::G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs)
75 : _g1(g1), _conc_refine_cards(0),
76 _ct_bs(ct_bs), _g1p(_g1->g1_policy()),
77 _cg1r(g1->concurrent_g1_refine()),
78 _cset_rs_update_cl(NULL),
79 _cards_scanned(NULL), _total_cards_scanned(0),
80 _prev_period_summary()
81 {
82 _seq_task = new SubTasksDone(NumSeqTasks);
83 _cset_rs_update_cl = NEW_C_HEAP_ARRAY(OopsInHeapRegionClosure*, n_workers(), mtGC);
84 for (uint i = 0; i < n_workers(); i++) {
85 _cset_rs_update_cl[i] = NULL;
86 }
87 if (G1SummarizeRSetStats) {
88 _prev_period_summary.initialize(this);
89 }
90 }
91
92 G1RemSet::~G1RemSet() {
93 delete _seq_task;
94 for (uint i = 0; i < n_workers(); i++) {
95 assert(_cset_rs_update_cl[i] == NULL, "it should be");
96 }
97 FREE_C_HEAP_ARRAY(OopsInHeapRegionClosure*, _cset_rs_update_cl, mtGC);
98 }
99
100 void CountNonCleanMemRegionClosure::do_MemRegion(MemRegion mr) {
101 if (_g1->is_in_g1_reserved(mr.start())) {
102 _n += (int) ((mr.byte_size() / CardTableModRefBS::card_size));
264 }
265
266 // Closure used for updating RSets and recording references that
267 // point into the collection set. Only called during an
268 // evacuation pause.
269
270 class RefineRecordRefsIntoCSCardTableEntryClosure: public CardTableEntryClosure {
271 G1RemSet* _g1rs;
272 DirtyCardQueue* _into_cset_dcq;
273 public:
274 RefineRecordRefsIntoCSCardTableEntryClosure(G1CollectedHeap* g1h,
275 DirtyCardQueue* into_cset_dcq) :
276 _g1rs(g1h->g1_rem_set()), _into_cset_dcq(into_cset_dcq)
277 {}
278 bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
279 // The only time we care about recording cards that
280 // contain references that point into the collection set
281 // is during RSet updating within an evacuation pause.
282 // In this case worker_i should be the id of a GC worker thread.
283 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
284 assert(worker_i < ParallelGCThreads, "should be a GC worker");
285
286 if (_g1rs->refine_card(card_ptr, worker_i, true)) {
287 // 'card_ptr' contains references that point into the collection
288 // set. We need to record the card in the DCQS
289 // (G1CollectedHeap::into_cset_dirty_card_queue_set())
290 // that's used for that purpose.
291 //
292 // Enqueue the card
293 _into_cset_dcq->enqueue(card_ptr);
294 }
295 return true;
296 }
297 };
298
299 void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) {
300 double start = os::elapsedTime();
301 // Apply the given closure to all remaining log entries.
302 RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
303
304 _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i);
325 #if CARD_REPEAT_HISTO
326 ct_freq_update_histo_and_reset();
327 #endif
328
329 // We cache the value of 'oc' closure into the appropriate slot in the
330 // _cset_rs_update_cl for this worker
331 assert(worker_i < n_workers(), "sanity");
332 _cset_rs_update_cl[worker_i] = oc;
333
334 // A DirtyCardQueue that is used to hold cards containing references
335 // that point into the collection set. This DCQ is associated with a
336 // special DirtyCardQueueSet (see g1CollectedHeap.hpp). Under normal
337 // circumstances (i.e. the pause successfully completes), these cards
338 // are just discarded (there's no need to update the RSets of regions
339 // that were in the collection set - after the pause these regions
340 // are wholly 'free' of live objects. In the event of an evacuation
341 // failure the cards/buffers in this queue set are passed to the
342 // DirtyCardQueueSet that is used to manage RSet updates
343 DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
344
345 updateRS(&into_cset_dcq, worker_i);
346 scanRS(oc, code_root_cl, worker_i);
347
348 // We now clear the cached values of _cset_rs_update_cl for this worker
349 _cset_rs_update_cl[worker_i] = NULL;
350 }
351
352 void G1RemSet::prepare_for_oops_into_collection_set_do() {
353 cleanupHRRS();
354 _g1->set_refine_cte_cl_concurrency(false);
355 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
356 dcqs.concatenate_logs();
357
358 guarantee( _cards_scanned == NULL, "invariant" );
359 _cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers(), mtGC);
360 for (uint i = 0; i < n_workers(); ++i) {
361 _cards_scanned[i] = 0;
362 }
363 _total_cards_scanned = 0;
364 }
400
401 class ScrubRSClosure: public HeapRegionClosure {
402 G1CollectedHeap* _g1h;
403 BitMap* _region_bm;
404 BitMap* _card_bm;
405 CardTableModRefBS* _ctbs;
406 public:
407 ScrubRSClosure(BitMap* region_bm, BitMap* card_bm) :
408 _g1h(G1CollectedHeap::heap()),
409 _region_bm(region_bm), _card_bm(card_bm),
410 _ctbs(_g1h->g1_barrier_set()) {}
411
412 bool doHeapRegion(HeapRegion* r) {
413 if (!r->is_continues_humongous()) {
414 r->rem_set()->scrub(_ctbs, _region_bm, _card_bm);
415 }
416 return false;
417 }
418 };
419
420 void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer *hrclaimer) {
421 ScrubRSClosure scrub_cl(region_bm, card_bm);
422 _g1->heap_region_par_iterate(&scrub_cl, worker_num, hrclaimer);
423 }
424
425 G1TriggerClosure::G1TriggerClosure() :
426 _triggered(false) { }
427
428 G1InvokeIfNotTriggeredClosure::G1InvokeIfNotTriggeredClosure(G1TriggerClosure* t_cl,
429 OopClosure* oop_cl) :
430 _trigger_cl(t_cl), _oop_cl(oop_cl) { }
431
432 G1Mux2Closure::G1Mux2Closure(OopClosure *c1, OopClosure *c2) :
433 _c1(c1), _c2(c2) { }
434
435 G1UpdateRSOrPushRefOopClosure::
436 G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h,
437 G1RemSet* rs,
438 OopsInHeapRegionClosure* push_ref_cl,
439 bool record_refs_into_cset,
440 uint worker_i) :
|