95 }
96
97 void CountNonCleanMemRegionClosure::do_MemRegion(MemRegion mr) {
98 if (_g1->is_in_g1_reserved(mr.start())) {
99 _n += (int) ((mr.byte_size() / CardTableModRefBS::card_size));
100 if (_start_first == NULL) _start_first = mr.start();
101 }
102 }
103
104 class ScanRSClosure : public HeapRegionClosure {
105 size_t _cards_done, _cards;
106 G1CollectedHeap* _g1h;
107
108 OopsInHeapRegionClosure* _oc;
109 CodeBlobToOopClosure* _code_root_cl;
110
111 G1BlockOffsetSharedArray* _bot_shared;
112 CardTableModRefBS *_ct_bs;
113
114 double _strong_code_root_scan_time_sec;
115 int _worker_i;
116 int _block_size;
117 bool _try_claimed;
118
119 public:
120 ScanRSClosure(OopsInHeapRegionClosure* oc,
121 CodeBlobToOopClosure* code_root_cl,
122 int worker_i) :
123 _oc(oc),
124 _code_root_cl(code_root_cl),
125 _strong_code_root_scan_time_sec(0.0),
126 _cards(0),
127 _cards_done(0),
128 _worker_i(worker_i),
129 _try_claimed(false)
130 {
131 _g1h = G1CollectedHeap::heap();
132 _bot_shared = _g1h->bot_shared();
133 _ct_bs = (CardTableModRefBS*) (_g1h->barrier_set());
134 _block_size = MAX2<int>(G1RSetScanBlockSize, 1);
135 }
136
137 void set_try_claimed() { _try_claimed = true; }
138
139 void scanCard(size_t index, HeapRegion *r) {
140 // Stack allocate the DirtyCardToOopClosure instance
141 HeapRegionDCTOC cl(_g1h, r, _oc,
142 CardTableModRefBS::Precise,
223 }
224 if (!_try_claimed) {
225 // Scan the strong code root list attached to the current region
226 scan_strong_code_roots(r);
227
228 hrrs->set_iter_complete();
229 }
230 return false;
231 }
232
233 double strong_code_root_scan_time_sec() {
234 return _strong_code_root_scan_time_sec;
235 }
236
237 size_t cards_done() { return _cards_done;}
238 size_t cards_looked_up() { return _cards;}
239 };
240
241 void G1RemSet::scanRS(OopsInHeapRegionClosure* oc,
242 CodeBlobToOopClosure* code_root_cl,
243 int worker_i) {
244 double rs_time_start = os::elapsedTime();
245 HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i);
246
247 ScanRSClosure scanRScl(oc, code_root_cl, worker_i);
248
249 _g1->collection_set_iterate_from(startRegion, &scanRScl);
250 scanRScl.set_try_claimed();
251 _g1->collection_set_iterate_from(startRegion, &scanRScl);
252
253 double scan_rs_time_sec = (os::elapsedTime() - rs_time_start)
254 - scanRScl.strong_code_root_scan_time_sec();
255
256 assert(_cards_scanned != NULL, "invariant");
257 _cards_scanned[worker_i] = scanRScl.cards_done();
258
259 _g1p->phase_times()->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
260 _g1p->phase_times()->record_strong_code_root_scan_time(worker_i,
261 scanRScl.strong_code_root_scan_time_sec() * 1000.0);
262 }
263
264 // Closure used for updating RSets and recording references that
265 // point into the collection set. Only called during an
266 // evacuation pause.
267
268 class RefineRecordRefsIntoCSCardTableEntryClosure: public CardTableEntryClosure {
269 G1RemSet* _g1rs;
270 DirtyCardQueue* _into_cset_dcq;
271 public:
272 RefineRecordRefsIntoCSCardTableEntryClosure(G1CollectedHeap* g1h,
273 DirtyCardQueue* into_cset_dcq) :
274 _g1rs(g1h->g1_rem_set()), _into_cset_dcq(into_cset_dcq)
275 {}
276 bool do_card_ptr(jbyte* card_ptr, int worker_i) {
277 // The only time we care about recording cards that
278 // contain references that point into the collection set
279 // is during RSet updating within an evacuation pause.
280 // In this case worker_i should be the id of a GC worker thread.
281 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
282 assert(worker_i < (int) (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker");
283
284 if (_g1rs->refine_card(card_ptr, worker_i, true)) {
285 // 'card_ptr' contains references that point into the collection
286 // set. We need to record the card in the DCQS
287 // (G1CollectedHeap::into_cset_dirty_card_queue_set())
288 // that's used for that purpose.
289 //
290 // Enqueue the card
291 _into_cset_dcq->enqueue(card_ptr);
292 }
293 return true;
294 }
295 };
296
297 void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) {
298 double start = os::elapsedTime();
299 // Apply the given closure to all remaining log entries.
300 RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
301
302 _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i);
303
304 // Now there should be no dirty cards.
305 if (G1RSLogCheckCardTable) {
306 CountNonCleanMemRegionClosure cl(_g1);
307 _ct_bs->mod_card_iterate(&cl);
308 // XXX This isn't true any more: keeping cards of young regions
309 // marked dirty broke it. Need some reasonable fix.
310 guarantee(cl.n() == 0, "Card table should be clean.");
311 }
312
313 _g1p->phase_times()->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0);
314 }
315
316 void G1RemSet::cleanupHRRS() {
317 HeapRegionRemSet::cleanup();
318 }
319
320 void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
321 CodeBlobToOopClosure* code_root_cl,
322 int worker_i) {
323 #if CARD_REPEAT_HISTO
324 ct_freq_update_histo_and_reset();
325 #endif
326
327 // We cache the value of 'oc' closure into the appropriate slot in the
328 // _cset_rs_update_cl for this worker
329 assert(worker_i < (int)n_workers(), "sanity");
330 _cset_rs_update_cl[worker_i] = oc;
331
332 // A DirtyCardQueue that is used to hold cards containing references
333 // that point into the collection set. This DCQ is associated with a
334 // special DirtyCardQueueSet (see g1CollectedHeap.hpp). Under normal
335 // circumstances (i.e. the pause successfully completes), these cards
336 // are just discarded (there's no need to update the RSets of regions
337 // that were in the collection set - after the pause these regions
338 // are wholly 'free' of live objects. In the event of an evacuation
339 // failure the cards/buffers in this queue set are:
340 // * passed to the DirtyCardQueueSet that is used to manage deferred
341 // RSet updates, or
342 // * scanned for references that point into the collection set
343 // and the RSet of the corresponding region in the collection set
344 // is updated immediately.
345 DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
346
347 assert((ParallelGCThreads > 0) || worker_i == 0, "invariant");
348
349 // The two flags below were introduced temporarily to serialize
386 _cards_scanned[i] = 0;
387 }
388 _total_cards_scanned = 0;
389 }
390
391
392 // This closure, applied to a DirtyCardQueueSet, is used to immediately
393 // update the RSets for the regions in the CSet. For each card it iterates
394 // through the oops which coincide with that card. It scans the reference
395 // fields in each oop; when it finds an oop that points into the collection
396 // set, the RSet for the region containing the referenced object is updated.
397 class UpdateRSetCardTableEntryIntoCSetClosure: public CardTableEntryClosure {
398 G1CollectedHeap* _g1;
399 CardTableModRefBS* _ct_bs;
400 public:
401 UpdateRSetCardTableEntryIntoCSetClosure(G1CollectedHeap* g1,
402 CardTableModRefBS* bs):
403 _g1(g1), _ct_bs(bs)
404 { }
405
406 bool do_card_ptr(jbyte* card_ptr, int worker_i) {
407 // Construct the region representing the card.
408 HeapWord* start = _ct_bs->addr_for(card_ptr);
409 // And find the region containing it.
410 HeapRegion* r = _g1->heap_region_containing(start);
411 assert(r != NULL, "unexpected null");
412
413 // Scan oops in the card looking for references into the collection set
414 // Don't use addr_for(card_ptr + 1) which can ask for
415 // a card beyond the heap. This is not safe without a perm
416 // gen.
417 HeapWord* end = start + CardTableModRefBS::card_size_in_words;
418 MemRegion scanRegion(start, end);
419
420 UpdateRSetImmediate update_rs_cl(_g1->g1_rem_set());
421 FilterIntoCSClosure update_rs_cset_oop_cl(NULL, _g1, &update_rs_cl);
422 FilterOutOfRegionClosure filter_then_update_rs_cset_oop_cl(r, &update_rs_cset_oop_cl);
423
424 // We can pass false as the "filter_young" parameter here as:
425 // * we should be in a STW pause,
426 // * the DCQS to which this closure is applied is used to hold
532 worker_num,
533 n_workers(),
534 claim_val);
535 }
536
537 G1TriggerClosure::G1TriggerClosure() :
538 _triggered(false) { }
539
540 G1InvokeIfNotTriggeredClosure::G1InvokeIfNotTriggeredClosure(G1TriggerClosure* t_cl,
541 OopClosure* oop_cl) :
542 _trigger_cl(t_cl), _oop_cl(oop_cl) { }
543
544 G1Mux2Closure::G1Mux2Closure(OopClosure *c1, OopClosure *c2) :
545 _c1(c1), _c2(c2) { }
546
547 G1UpdateRSOrPushRefOopClosure::
548 G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h,
549 G1RemSet* rs,
550 OopsInHeapRegionClosure* push_ref_cl,
551 bool record_refs_into_cset,
552 int worker_i) :
553 _g1(g1h), _g1_rem_set(rs), _from(NULL),
554 _record_refs_into_cset(record_refs_into_cset),
555 _push_ref_cl(push_ref_cl), _worker_i(worker_i) { }
556
557 // Returns true if the given card contains references that point
558 // into the collection set, if we're checking for such references;
559 // false otherwise.
560
561 bool G1RemSet::refine_card(jbyte* card_ptr, int worker_i,
562 bool check_for_refs_into_cset) {
563
564 // If the card is no longer dirty, nothing to do.
565 if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
566 // No need to return that this card contains refs that point
567 // into the collection set.
568 return false;
569 }
570
571 // Construct the region representing the card.
572 HeapWord* start = _ct_bs->addr_for(card_ptr);
573 // And find the region containing it.
574 HeapRegion* r = _g1->heap_region_containing(start);
575 if (r == NULL) {
576 // Again no need to return that this card contains refs that
577 // point into the collection set.
578 return false; // Not in the G1 heap (might be in perm, for example.)
579 }
580
581 // Why do we have to check here whether a card is on a young region,
|
95 }
96
97 void CountNonCleanMemRegionClosure::do_MemRegion(MemRegion mr) {
98 if (_g1->is_in_g1_reserved(mr.start())) {
99 _n += (int) ((mr.byte_size() / CardTableModRefBS::card_size));
100 if (_start_first == NULL) _start_first = mr.start();
101 }
102 }
103
104 class ScanRSClosure : public HeapRegionClosure {
105 size_t _cards_done, _cards;
106 G1CollectedHeap* _g1h;
107
108 OopsInHeapRegionClosure* _oc;
109 CodeBlobToOopClosure* _code_root_cl;
110
111 G1BlockOffsetSharedArray* _bot_shared;
112 CardTableModRefBS *_ct_bs;
113
114 double _strong_code_root_scan_time_sec;
115 uint _worker_i;
116 int _block_size;
117 bool _try_claimed;
118
119 public:
120 ScanRSClosure(OopsInHeapRegionClosure* oc,
121 CodeBlobToOopClosure* code_root_cl,
122 uint worker_i) :
123 _oc(oc),
124 _code_root_cl(code_root_cl),
125 _strong_code_root_scan_time_sec(0.0),
126 _cards(0),
127 _cards_done(0),
128 _worker_i(worker_i),
129 _try_claimed(false)
130 {
131 _g1h = G1CollectedHeap::heap();
132 _bot_shared = _g1h->bot_shared();
133 _ct_bs = (CardTableModRefBS*) (_g1h->barrier_set());
134 _block_size = MAX2<int>(G1RSetScanBlockSize, 1);
135 }
136
137 void set_try_claimed() { _try_claimed = true; }
138
139 void scanCard(size_t index, HeapRegion *r) {
140 // Stack allocate the DirtyCardToOopClosure instance
141 HeapRegionDCTOC cl(_g1h, r, _oc,
142 CardTableModRefBS::Precise,
223 }
224 if (!_try_claimed) {
225 // Scan the strong code root list attached to the current region
226 scan_strong_code_roots(r);
227
228 hrrs->set_iter_complete();
229 }
230 return false;
231 }
232
233 double strong_code_root_scan_time_sec() {
234 return _strong_code_root_scan_time_sec;
235 }
236
237 size_t cards_done() { return _cards_done;}
238 size_t cards_looked_up() { return _cards;}
239 };
240
241 void G1RemSet::scanRS(OopsInHeapRegionClosure* oc,
242 CodeBlobToOopClosure* code_root_cl,
243 uint worker_i) {
244 double rs_time_start = os::elapsedTime();
245 HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i);
246
247 ScanRSClosure scanRScl(oc, code_root_cl, worker_i);
248
249 _g1->collection_set_iterate_from(startRegion, &scanRScl);
250 scanRScl.set_try_claimed();
251 _g1->collection_set_iterate_from(startRegion, &scanRScl);
252
253 double scan_rs_time_sec = (os::elapsedTime() - rs_time_start)
254 - scanRScl.strong_code_root_scan_time_sec();
255
256 assert(_cards_scanned != NULL, "invariant");
257 _cards_scanned[worker_i] = scanRScl.cards_done();
258
259 _g1p->phase_times()->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
260 _g1p->phase_times()->record_strong_code_root_scan_time(worker_i,
261 scanRScl.strong_code_root_scan_time_sec() * 1000.0);
262 }
263
264 // Closure used for updating RSets and recording references that
265 // point into the collection set. Only called during an
266 // evacuation pause.
267
268 class RefineRecordRefsIntoCSCardTableEntryClosure: public CardTableEntryClosure {
269 G1RemSet* _g1rs;
270 DirtyCardQueue* _into_cset_dcq;
271 public:
272 RefineRecordRefsIntoCSCardTableEntryClosure(G1CollectedHeap* g1h,
273 DirtyCardQueue* into_cset_dcq) :
274 _g1rs(g1h->g1_rem_set()), _into_cset_dcq(into_cset_dcq)
275 {}
276 bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
277 // The only time we care about recording cards that
278 // contain references that point into the collection set
279 // is during RSet updating within an evacuation pause.
280 // In this case worker_i should be the id of a GC worker thread.
281 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
282 assert(worker_i < (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker");
283
284 if (_g1rs->refine_card(card_ptr, worker_i, true)) {
285 // 'card_ptr' contains references that point into the collection
286 // set. We need to record the card in the DCQS
287 // (G1CollectedHeap::into_cset_dirty_card_queue_set())
288 // that's used for that purpose.
289 //
290 // Enqueue the card
291 _into_cset_dcq->enqueue(card_ptr);
292 }
293 return true;
294 }
295 };
296
297 void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) {
298 double start = os::elapsedTime();
299 // Apply the given closure to all remaining log entries.
300 RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
301
302 _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i);
303
304 // Now there should be no dirty cards.
305 if (G1RSLogCheckCardTable) {
306 CountNonCleanMemRegionClosure cl(_g1);
307 _ct_bs->mod_card_iterate(&cl);
308 // XXX This isn't true any more: keeping cards of young regions
309 // marked dirty broke it. Need some reasonable fix.
310 guarantee(cl.n() == 0, "Card table should be clean.");
311 }
312
313 _g1p->phase_times()->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0);
314 }
315
316 void G1RemSet::cleanupHRRS() {
317 HeapRegionRemSet::cleanup();
318 }
319
320 void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
321 CodeBlobToOopClosure* code_root_cl,
322 uint worker_i) {
323 #if CARD_REPEAT_HISTO
324 ct_freq_update_histo_and_reset();
325 #endif
326
327 // We cache the value of 'oc' closure into the appropriate slot in the
328 // _cset_rs_update_cl for this worker
329 assert(worker_i < n_workers(), "sanity");
330 _cset_rs_update_cl[worker_i] = oc;
331
332 // A DirtyCardQueue that is used to hold cards containing references
333 // that point into the collection set. This DCQ is associated with a
334 // special DirtyCardQueueSet (see g1CollectedHeap.hpp). Under normal
335 // circumstances (i.e. the pause successfully completes), these cards
336 // are just discarded (there's no need to update the RSets of regions
337 // that were in the collection set - after the pause these regions
338 // are wholly 'free' of live objects. In the event of an evacuation
339 // failure the cards/buffers in this queue set are:
340 // * passed to the DirtyCardQueueSet that is used to manage deferred
341 // RSet updates, or
342 // * scanned for references that point into the collection set
343 // and the RSet of the corresponding region in the collection set
344 // is updated immediately.
345 DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
346
347 assert((ParallelGCThreads > 0) || worker_i == 0, "invariant");
348
349 // The two flags below were introduced temporarily to serialize
386 _cards_scanned[i] = 0;
387 }
388 _total_cards_scanned = 0;
389 }
390
391
392 // This closure, applied to a DirtyCardQueueSet, is used to immediately
393 // update the RSets for the regions in the CSet. For each card it iterates
394 // through the oops which coincide with that card. It scans the reference
395 // fields in each oop; when it finds an oop that points into the collection
396 // set, the RSet for the region containing the referenced object is updated.
397 class UpdateRSetCardTableEntryIntoCSetClosure: public CardTableEntryClosure {
398 G1CollectedHeap* _g1;
399 CardTableModRefBS* _ct_bs;
400 public:
401 UpdateRSetCardTableEntryIntoCSetClosure(G1CollectedHeap* g1,
402 CardTableModRefBS* bs):
403 _g1(g1), _ct_bs(bs)
404 { }
405
406 bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
407 // Construct the region representing the card.
408 HeapWord* start = _ct_bs->addr_for(card_ptr);
409 // And find the region containing it.
410 HeapRegion* r = _g1->heap_region_containing(start);
411 assert(r != NULL, "unexpected null");
412
413 // Scan oops in the card looking for references into the collection set
414 // Don't use addr_for(card_ptr + 1) which can ask for
415 // a card beyond the heap. This is not safe without a perm
416 // gen.
417 HeapWord* end = start + CardTableModRefBS::card_size_in_words;
418 MemRegion scanRegion(start, end);
419
420 UpdateRSetImmediate update_rs_cl(_g1->g1_rem_set());
421 FilterIntoCSClosure update_rs_cset_oop_cl(NULL, _g1, &update_rs_cl);
422 FilterOutOfRegionClosure filter_then_update_rs_cset_oop_cl(r, &update_rs_cset_oop_cl);
423
424 // We can pass false as the "filter_young" parameter here as:
425 // * we should be in a STW pause,
426 // * the DCQS to which this closure is applied is used to hold
532 worker_num,
533 n_workers(),
534 claim_val);
535 }
536
537 G1TriggerClosure::G1TriggerClosure() :
538 _triggered(false) { }
539
540 G1InvokeIfNotTriggeredClosure::G1InvokeIfNotTriggeredClosure(G1TriggerClosure* t_cl,
541 OopClosure* oop_cl) :
542 _trigger_cl(t_cl), _oop_cl(oop_cl) { }
543
544 G1Mux2Closure::G1Mux2Closure(OopClosure *c1, OopClosure *c2) :
545 _c1(c1), _c2(c2) { }
546
547 G1UpdateRSOrPushRefOopClosure::
548 G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h,
549 G1RemSet* rs,
550 OopsInHeapRegionClosure* push_ref_cl,
551 bool record_refs_into_cset,
552 uint worker_i) :
553 _g1(g1h), _g1_rem_set(rs), _from(NULL),
554 _record_refs_into_cset(record_refs_into_cset),
555 _push_ref_cl(push_ref_cl), _worker_i(worker_i) { }
556
557 // Returns true if the given card contains references that point
558 // into the collection set, if we're checking for such references;
559 // false otherwise.
560
561 bool G1RemSet::refine_card(jbyte* card_ptr, uint worker_i,
562 bool check_for_refs_into_cset) {
563
564 // If the card is no longer dirty, nothing to do.
565 if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
566 // No need to return that this card contains refs that point
567 // into the collection set.
568 return false;
569 }
570
571 // Construct the region representing the card.
572 HeapWord* start = _ct_bs->addr_for(card_ptr);
573 // And find the region containing it.
574 HeapRegion* r = _g1->heap_region_containing(start);
575 if (r == NULL) {
576 // Again no need to return that this card contains refs that
577 // point into the collection set.
578 return false; // Not in the G1 heap (might be in perm, for example.)
579 }
580
581 // Why do we have to check here whether a card is on a young region,
|