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);
98 }
99
100 class ScanRSClosure : public HeapRegionClosure {
101 size_t _cards_done, _cards;
102 G1CollectedHeap* _g1h;
103
104 OopsInHeapRegionClosure* _oc;
105 CodeBlobClosure* _code_root_cl;
106
107 G1BlockOffsetSharedArray* _bot_shared;
108 G1SATBCardTableModRefBS *_ct_bs;
109
110 double _strong_code_root_scan_time_sec;
111 uint _worker_i;
112 int _block_size;
113 bool _try_claimed;
114
115 public:
116 ScanRSClosure(OopsInHeapRegionClosure* oc,
117 CodeBlobClosure* code_root_cl,
118 uint worker_i) :
119 _oc(oc),
120 _code_root_cl(code_root_cl),
121 _strong_code_root_scan_time_sec(0.0),
122 _cards(0),
123 _cards_done(0),
124 _worker_i(worker_i),
125 _try_claimed(false)
126 {
127 _g1h = G1CollectedHeap::heap();
128 _bot_shared = _g1h->bot_shared();
129 _ct_bs = _g1h->g1_barrier_set();
130 _block_size = MAX2<int>(G1RSetScanBlockSize, 1);
131 }
132
133 void set_try_claimed() { _try_claimed = true; }
134
135 void scanCard(size_t index, HeapRegion *r) {
136 // Stack allocate the DirtyCardToOopClosure instance
137 HeapRegionDCTOC cl(_g1h, r, _oc,
138 CardTableModRefBS::Precise,
139 HeapRegionDCTOC::IntoCSFilterKind);
140
141 // Set the "from" region in the closure.
142 _oc->set_region(r);
143 MemRegion card_region(_bot_shared->address_for_index(index), G1BlockOffsetSharedArray::N_words);
144 MemRegion pre_gc_allocated(r->bottom(), r->scan_top());
145 MemRegion mr = pre_gc_allocated.intersection(card_region);
146 if (!mr.is_empty() && !_ct_bs->is_card_claimed(index)) {
147 // We make the card as "claimed" lazily (so races are possible
148 // but they're benign), which reduces the number of duplicate
149 // scans (the rsets of the regions in the cset can intersect).
150 _ct_bs->set_card_claimed(index);
151 _cards_done++;
152 cl.do_MemRegion(mr);
153 }
154 }
155
156 void printCard(HeapRegion* card_region, size_t card_index,
157 HeapWord* card_start) {
158 gclog_or_tty->print_cr("T %u Region [" PTR_FORMAT ", " PTR_FORMAT ") "
159 "RS names card " SIZE_FORMAT_HEX ": "
214 scanCard(card_index, card_region);
215 }
216 }
217 if (!_try_claimed) {
218 // Scan the strong code root list attached to the current region
219 scan_strong_code_roots(r);
220
221 hrrs->set_iter_complete();
222 }
223 return false;
224 }
225
226 double strong_code_root_scan_time_sec() {
227 return _strong_code_root_scan_time_sec;
228 }
229
230 size_t cards_done() { return _cards_done;}
231 size_t cards_looked_up() { return _cards;}
232 };
233
234 void G1RemSet::scanRS(OopsInHeapRegionClosure* oc,
235 CodeBlobClosure* code_root_cl,
236 uint worker_i) {
237 double rs_time_start = os::elapsedTime();
238 HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i);
239
240 ScanRSClosure scanRScl(oc, code_root_cl, worker_i);
241
242 _g1->collection_set_iterate_from(startRegion, &scanRScl);
243 scanRScl.set_try_claimed();
244 _g1->collection_set_iterate_from(startRegion, &scanRScl);
245
246 double scan_rs_time_sec = (os::elapsedTime() - rs_time_start)
247 - scanRScl.strong_code_root_scan_time_sec();
248
249 assert(_cards_scanned != NULL, "invariant");
250 _cards_scanned[worker_i] = scanRScl.cards_done();
251
252 _g1p->phase_times()->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
253 _g1p->phase_times()->record_strong_code_root_scan_time(worker_i,
254 scanRScl.strong_code_root_scan_time_sec() * 1000.0);
284 _into_cset_dcq->enqueue(card_ptr);
285 }
286 return true;
287 }
288 };
289
290 void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) {
291 double start = os::elapsedTime();
292 // Apply the given closure to all remaining log entries.
293 RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
294
295 _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i);
296
297 _g1p->phase_times()->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0);
298 }
299
300 void G1RemSet::cleanupHRRS() {
301 HeapRegionRemSet::cleanup();
302 }
303
304 void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
305 CodeBlobClosure* code_root_cl,
306 uint worker_i) {
307 #if CARD_REPEAT_HISTO
308 ct_freq_update_histo_and_reset();
309 #endif
310
311 // We cache the value of 'oc' closure into the appropriate slot in the
312 // _cset_rs_update_cl for this worker
313 assert(worker_i < n_workers(), "sanity");
314 _cset_rs_update_cl[worker_i] = oc;
315
316 // A DirtyCardQueue that is used to hold cards containing references
317 // that point into the collection set. This DCQ is associated with a
318 // special DirtyCardQueueSet (see g1CollectedHeap.hpp). Under normal
319 // circumstances (i.e. the pause successfully completes), these cards
320 // are just discarded (there's no need to update the RSets of regions
321 // that were in the collection set - after the pause these regions
322 // are wholly 'free' of live objects. In the event of an evacuation
323 // failure the cards/buffers in this queue set are passed to the
324 // DirtyCardQueueSet that is used to manage RSet updates
400 };
401
402 void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer *hrclaimer) {
403 ScrubRSClosure scrub_cl(region_bm, card_bm);
404 _g1->heap_region_par_iterate(&scrub_cl, worker_num, hrclaimer);
405 }
406
407 G1TriggerClosure::G1TriggerClosure() :
408 _triggered(false) { }
409
410 G1InvokeIfNotTriggeredClosure::G1InvokeIfNotTriggeredClosure(G1TriggerClosure* t_cl,
411 OopClosure* oop_cl) :
412 _trigger_cl(t_cl), _oop_cl(oop_cl) { }
413
414 G1Mux2Closure::G1Mux2Closure(OopClosure *c1, OopClosure *c2) :
415 _c1(c1), _c2(c2) { }
416
417 G1UpdateRSOrPushRefOopClosure::
418 G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h,
419 G1RemSet* rs,
420 OopsInHeapRegionClosure* push_ref_cl,
421 bool record_refs_into_cset,
422 uint worker_i) :
423 _g1(g1h), _g1_rem_set(rs), _from(NULL),
424 _record_refs_into_cset(record_refs_into_cset),
425 _push_ref_cl(push_ref_cl), _worker_i(worker_i) { }
426
427 // Returns true if the given card contains references that point
428 // into the collection set, if we're checking for such references;
429 // false otherwise.
430
431 bool G1RemSet::refine_card(jbyte* card_ptr, uint worker_i,
432 bool check_for_refs_into_cset) {
433 assert(_g1->is_in_exact(_ct_bs->addr_for(card_ptr)),
434 err_msg("Card at "PTR_FORMAT" index "SIZE_FORMAT" representing heap at "PTR_FORMAT" (%u) must be in committed heap",
435 p2i(card_ptr),
436 _ct_bs->index_for(_ct_bs->addr_for(card_ptr)),
437 _ct_bs->addr_for(card_ptr),
438 _g1->addr_to_region(_ct_bs->addr_for(card_ptr))));
439
440 // If the card is no longer dirty, nothing to do.
501 start = _ct_bs->addr_for(card_ptr);
502 r = _g1->heap_region_containing(start);
503
504 // Checking whether the region we got back from the cache
505 // is young here is inappropriate. The region could have been
506 // freed, reallocated and tagged as young while in the cache.
507 // Hence we could see its young type change at any time.
508 }
509
510 // Don't use addr_for(card_ptr + 1) which can ask for
511 // a card beyond the heap. This is not safe without a perm
512 // gen at the upper end of the heap.
513 HeapWord* end = start + CardTableModRefBS::card_size_in_words;
514 MemRegion dirtyRegion(start, end);
515
516 #if CARD_REPEAT_HISTO
517 init_ct_freq_table(_g1->max_capacity());
518 ct_freq_note_card(_ct_bs->index_for(start));
519 #endif
520
521 OopsInHeapRegionClosure* oops_in_heap_closure = NULL;
522 if (check_for_refs_into_cset) {
523 // ConcurrentG1RefineThreads have worker numbers larger than what
524 // _cset_rs_update_cl[] is set up to handle. But those threads should
525 // only be active outside of a collection which means that when they
526 // reach here they should have check_for_refs_into_cset == false.
527 assert((size_t)worker_i < n_workers(), "index of worker larger than _cset_rs_update_cl[].length");
528 oops_in_heap_closure = _cset_rs_update_cl[worker_i];
529 }
530 G1UpdateRSOrPushRefOopClosure update_rs_oop_cl(_g1,
531 _g1->g1_rem_set(),
532 oops_in_heap_closure,
533 check_for_refs_into_cset,
534 worker_i);
535 update_rs_oop_cl.set_from(r);
536
537 G1TriggerClosure trigger_cl;
538 FilterIntoCSClosure into_cs_cl(NULL, _g1, &trigger_cl);
539 G1InvokeIfNotTriggeredClosure invoke_cl(&trigger_cl, &into_cs_cl);
540 G1Mux2Closure mux(&invoke_cl, &update_rs_oop_cl);
541
|
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(G1ParPushHeapRSClosure*, 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(G1ParPushHeapRSClosure*, _cset_rs_update_cl);
98 }
99
100 class ScanRSClosure : public HeapRegionClosure {
101 size_t _cards_done, _cards;
102 G1CollectedHeap* _g1h;
103
104 G1ParPushHeapRSClosure* _oc;
105 CodeBlobClosure* _code_root_cl;
106
107 G1BlockOffsetSharedArray* _bot_shared;
108 G1SATBCardTableModRefBS *_ct_bs;
109
110 double _strong_code_root_scan_time_sec;
111 uint _worker_i;
112 int _block_size;
113 bool _try_claimed;
114
115 public:
116 ScanRSClosure(G1ParPushHeapRSClosure* oc,
117 CodeBlobClosure* code_root_cl,
118 uint worker_i) :
119 _oc(oc),
120 _code_root_cl(code_root_cl),
121 _strong_code_root_scan_time_sec(0.0),
122 _cards(0),
123 _cards_done(0),
124 _worker_i(worker_i),
125 _try_claimed(false)
126 {
127 _g1h = G1CollectedHeap::heap();
128 _bot_shared = _g1h->bot_shared();
129 _ct_bs = _g1h->g1_barrier_set();
130 _block_size = MAX2<int>(G1RSetScanBlockSize, 1);
131 }
132
133 void set_try_claimed() { _try_claimed = true; }
134
135 void scanCard(size_t index, HeapRegion *r) {
136 // Stack allocate the DirtyCardToOopClosure instance
137 HeapRegionDCTOC cl(_g1h, r, _oc,
138 CardTableModRefBS::Precise);
139
140 // Set the "from" region in the closure.
141 _oc->set_region(r);
142 MemRegion card_region(_bot_shared->address_for_index(index), G1BlockOffsetSharedArray::N_words);
143 MemRegion pre_gc_allocated(r->bottom(), r->scan_top());
144 MemRegion mr = pre_gc_allocated.intersection(card_region);
145 if (!mr.is_empty() && !_ct_bs->is_card_claimed(index)) {
146 // We make the card as "claimed" lazily (so races are possible
147 // but they're benign), which reduces the number of duplicate
148 // scans (the rsets of the regions in the cset can intersect).
149 _ct_bs->set_card_claimed(index);
150 _cards_done++;
151 cl.do_MemRegion(mr);
152 }
153 }
154
155 void printCard(HeapRegion* card_region, size_t card_index,
156 HeapWord* card_start) {
157 gclog_or_tty->print_cr("T %u Region [" PTR_FORMAT ", " PTR_FORMAT ") "
158 "RS names card " SIZE_FORMAT_HEX ": "
213 scanCard(card_index, card_region);
214 }
215 }
216 if (!_try_claimed) {
217 // Scan the strong code root list attached to the current region
218 scan_strong_code_roots(r);
219
220 hrrs->set_iter_complete();
221 }
222 return false;
223 }
224
225 double strong_code_root_scan_time_sec() {
226 return _strong_code_root_scan_time_sec;
227 }
228
229 size_t cards_done() { return _cards_done;}
230 size_t cards_looked_up() { return _cards;}
231 };
232
233 void G1RemSet::scanRS(G1ParPushHeapRSClosure* oc,
234 CodeBlobClosure* code_root_cl,
235 uint worker_i) {
236 double rs_time_start = os::elapsedTime();
237 HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i);
238
239 ScanRSClosure scanRScl(oc, code_root_cl, worker_i);
240
241 _g1->collection_set_iterate_from(startRegion, &scanRScl);
242 scanRScl.set_try_claimed();
243 _g1->collection_set_iterate_from(startRegion, &scanRScl);
244
245 double scan_rs_time_sec = (os::elapsedTime() - rs_time_start)
246 - scanRScl.strong_code_root_scan_time_sec();
247
248 assert(_cards_scanned != NULL, "invariant");
249 _cards_scanned[worker_i] = scanRScl.cards_done();
250
251 _g1p->phase_times()->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
252 _g1p->phase_times()->record_strong_code_root_scan_time(worker_i,
253 scanRScl.strong_code_root_scan_time_sec() * 1000.0);
283 _into_cset_dcq->enqueue(card_ptr);
284 }
285 return true;
286 }
287 };
288
289 void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) {
290 double start = os::elapsedTime();
291 // Apply the given closure to all remaining log entries.
292 RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
293
294 _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i);
295
296 _g1p->phase_times()->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0);
297 }
298
299 void G1RemSet::cleanupHRRS() {
300 HeapRegionRemSet::cleanup();
301 }
302
303 void G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc,
304 CodeBlobClosure* code_root_cl,
305 uint worker_i) {
306 #if CARD_REPEAT_HISTO
307 ct_freq_update_histo_and_reset();
308 #endif
309
310 // We cache the value of 'oc' closure into the appropriate slot in the
311 // _cset_rs_update_cl for this worker
312 assert(worker_i < n_workers(), "sanity");
313 _cset_rs_update_cl[worker_i] = oc;
314
315 // A DirtyCardQueue that is used to hold cards containing references
316 // that point into the collection set. This DCQ is associated with a
317 // special DirtyCardQueueSet (see g1CollectedHeap.hpp). Under normal
318 // circumstances (i.e. the pause successfully completes), these cards
319 // are just discarded (there's no need to update the RSets of regions
320 // that were in the collection set - after the pause these regions
321 // are wholly 'free' of live objects. In the event of an evacuation
322 // failure the cards/buffers in this queue set are passed to the
323 // DirtyCardQueueSet that is used to manage RSet updates
399 };
400
401 void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer *hrclaimer) {
402 ScrubRSClosure scrub_cl(region_bm, card_bm);
403 _g1->heap_region_par_iterate(&scrub_cl, worker_num, hrclaimer);
404 }
405
406 G1TriggerClosure::G1TriggerClosure() :
407 _triggered(false) { }
408
409 G1InvokeIfNotTriggeredClosure::G1InvokeIfNotTriggeredClosure(G1TriggerClosure* t_cl,
410 OopClosure* oop_cl) :
411 _trigger_cl(t_cl), _oop_cl(oop_cl) { }
412
413 G1Mux2Closure::G1Mux2Closure(OopClosure *c1, OopClosure *c2) :
414 _c1(c1), _c2(c2) { }
415
416 G1UpdateRSOrPushRefOopClosure::
417 G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h,
418 G1RemSet* rs,
419 G1ParPushHeapRSClosure* push_ref_cl,
420 bool record_refs_into_cset,
421 uint worker_i) :
422 _g1(g1h), _g1_rem_set(rs), _from(NULL),
423 _record_refs_into_cset(record_refs_into_cset),
424 _push_ref_cl(push_ref_cl), _worker_i(worker_i) { }
425
426 // Returns true if the given card contains references that point
427 // into the collection set, if we're checking for such references;
428 // false otherwise.
429
430 bool G1RemSet::refine_card(jbyte* card_ptr, uint worker_i,
431 bool check_for_refs_into_cset) {
432 assert(_g1->is_in_exact(_ct_bs->addr_for(card_ptr)),
433 err_msg("Card at "PTR_FORMAT" index "SIZE_FORMAT" representing heap at "PTR_FORMAT" (%u) must be in committed heap",
434 p2i(card_ptr),
435 _ct_bs->index_for(_ct_bs->addr_for(card_ptr)),
436 _ct_bs->addr_for(card_ptr),
437 _g1->addr_to_region(_ct_bs->addr_for(card_ptr))));
438
439 // If the card is no longer dirty, nothing to do.
500 start = _ct_bs->addr_for(card_ptr);
501 r = _g1->heap_region_containing(start);
502
503 // Checking whether the region we got back from the cache
504 // is young here is inappropriate. The region could have been
505 // freed, reallocated and tagged as young while in the cache.
506 // Hence we could see its young type change at any time.
507 }
508
509 // Don't use addr_for(card_ptr + 1) which can ask for
510 // a card beyond the heap. This is not safe without a perm
511 // gen at the upper end of the heap.
512 HeapWord* end = start + CardTableModRefBS::card_size_in_words;
513 MemRegion dirtyRegion(start, end);
514
515 #if CARD_REPEAT_HISTO
516 init_ct_freq_table(_g1->max_capacity());
517 ct_freq_note_card(_ct_bs->index_for(start));
518 #endif
519
520 G1ParPushHeapRSClosure* oops_in_heap_closure = NULL;
521 if (check_for_refs_into_cset) {
522 // ConcurrentG1RefineThreads have worker numbers larger than what
523 // _cset_rs_update_cl[] is set up to handle. But those threads should
524 // only be active outside of a collection which means that when they
525 // reach here they should have check_for_refs_into_cset == false.
526 assert((size_t)worker_i < n_workers(), "index of worker larger than _cset_rs_update_cl[].length");
527 oops_in_heap_closure = _cset_rs_update_cl[worker_i];
528 }
529 G1UpdateRSOrPushRefOopClosure update_rs_oop_cl(_g1,
530 _g1->g1_rem_set(),
531 oops_in_heap_closure,
532 check_for_refs_into_cset,
533 worker_i);
534 update_rs_oop_cl.set_from(r);
535
536 G1TriggerClosure trigger_cl;
537 FilterIntoCSClosure into_cs_cl(NULL, _g1, &trigger_cl);
538 G1InvokeIfNotTriggeredClosure invoke_cl(&trigger_cl, &into_cs_cl);
539 G1Mux2Closure mux(&invoke_cl, &update_rs_oop_cl);
540
|