289 _prev_period_summary() {
290 }
291
292 G1RemSet::~G1RemSet() {
293 if (_scan_state != NULL) {
294 delete _scan_state;
295 }
296 }
297
298 uint G1RemSet::num_par_rem_sets() {
299 return DirtyCardQueueSet::num_par_ids() + G1ConcurrentRefine::max_num_threads() + MAX2(ConcGCThreads, ParallelGCThreads);
300 }
301
302 void G1RemSet::initialize(size_t capacity, uint max_regions) {
303 G1FromCardCache::initialize(num_par_rem_sets(), max_regions);
304 _scan_state->initialize(max_regions);
305 }
306
307 G1ScanRSForRegionClosure::G1ScanRSForRegionClosure(G1RemSetScanState* scan_state,
308 G1ScanObjsDuringScanRSClosure* scan_obj_on_card,
309 CodeBlobClosure* code_root_cl,
310 uint worker_i) :
311 _scan_state(scan_state),
312 _scan_objs_on_card_cl(scan_obj_on_card),
313 _code_root_cl(code_root_cl),
314 _strong_code_root_scan_time_sec(0.0),
315 _cards_claimed(0),
316 _cards_scanned(0),
317 _cards_skipped(0),
318 _worker_i(worker_i) {
319 _g1h = G1CollectedHeap::heap();
320 _bot = _g1h->bot();
321 _ct = _g1h->card_table();
322 }
323
324 void G1ScanRSForRegionClosure::scan_card(MemRegion mr, uint region_idx_for_card) {
325 HeapRegion* const card_region = _g1h->region_at(region_idx_for_card);
326 _scan_objs_on_card_cl->set_region(card_region);
327 card_region->oops_on_card_seq_iterate_careful<true>(mr, _scan_objs_on_card_cl);
328 _scan_objs_on_card_cl->trim_queue_partially();
329 _cards_scanned++;
330 }
331
332 void G1ScanRSForRegionClosure::scan_strong_code_roots(HeapRegion* r) {
333 double scan_start = os::elapsedTime();
334 r->strong_code_roots_do(_code_root_cl);
335 _strong_code_root_scan_time_sec += (os::elapsedTime() - scan_start);
336 }
337
338 void G1ScanRSForRegionClosure::claim_card(size_t card_index, const uint region_idx_for_card){
339 _ct->set_card_claimed(card_index);
340 _scan_state->add_dirty_region(region_idx_for_card);
341 }
342
343 bool G1ScanRSForRegionClosure::do_heap_region(HeapRegion* r) {
344 assert(r->in_collection_set(), "should only be called on elements of CS.");
345 uint region_idx = r->hrm_index();
346
347 if (_scan_state->iter_is_complete(region_idx)) {
348 return false;
349 }
350 if (_scan_state->claim_iter(region_idx)) {
351 // If we ever free the collection set concurrently, we should also
352 // clear the card table concurrently therefore we won't need to
353 // add regions of the collection set to the dirty cards region.
354 _scan_state->add_dirty_region(region_idx);
355 }
356
357 // We claim cards in blocks so as to reduce the contention.
358 size_t const block_size = G1RSetScanBlockSize;
359
360 HeapRegionRemSetIterator iter(r->rem_set());
361 size_t card_index;
362
363 size_t claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
364 for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
365 if (current_card >= claimed_card_block + block_size) {
366 claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
367 }
368 if (current_card < claimed_card_block) {
369 _cards_skipped++;
381
382 assert(_g1h->region_at(region_idx_for_card)->is_in_reserved(card_start),
383 "Card start " PTR_FORMAT " to scan outside of region %u", p2i(card_start), _g1h->region_at(region_idx_for_card)->hrm_index());
384 HeapWord* const top = _scan_state->scan_top(region_idx_for_card);
385 if (card_start >= top) {
386 continue;
387 }
388
389 // We claim lazily (so races are possible but they're benign), which reduces the
390 // number of duplicate scans (the rsets of the regions in the cset can intersect).
391 // Claim the card after checking bounds above: the remembered set may contain
392 // random cards into current survivor, and we would then have an incorrectly
393 // claimed card in survivor space. Card table clear does not reset the card table
394 // of survivor space regions.
395 claim_card(card_index, region_idx_for_card);
396
397 MemRegion const mr(card_start, MIN2(card_start + BOTConstants::N_words, top));
398
399 scan_card(mr, region_idx_for_card);
400 }
401 if (_scan_state->set_iter_complete(region_idx)) {
402 // Scan the strong code root list attached to the current region
403 scan_strong_code_roots(r);
404 }
405 return false;
406 }
407
408 void G1RemSet::scan_rem_set(G1ParScanThreadState* pss,
409 uint worker_i) {
410 double rs_time_start = os::elapsedTime();
411
412 CodeBlobClosure* heap_region_codeblobs = pss->closures()->weak_codeblobs();
413
414 G1ScanObjsDuringScanRSClosure scan_cl(_g1h, pss);
415 G1ScanRSForRegionClosure cl(_scan_state, &scan_cl, heap_region_codeblobs, worker_i);
416 _g1h->collection_set_iterate_from(&cl, worker_i);
417
418 double scan_rs_time_sec = (os::elapsedTime() - rs_time_start) -
419 cl.strong_code_root_scan_time_sec();
420
421 G1GCPhaseTimes* p = _g1p->phase_times();
422
423 double scan_rs_trim_queue_time = TicksToTimeHelper::seconds(scan_cl.trim_ticks_and_reset());
424
425 p->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, scan_rs_time_sec);
426 p->move_time_secs(G1GCPhaseTimes::ScanRS, G1GCPhaseTimes::ObjCopy, worker_i, scan_rs_trim_queue_time);
427
428 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_scanned(), G1GCPhaseTimes::ScanRSScannedCards);
429 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_claimed(), G1GCPhaseTimes::ScanRSClaimedCards);
430 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_skipped(), G1GCPhaseTimes::ScanRSSkippedCards);
431
432 p->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, cl.strong_code_root_scan_time_sec());
433 p->move_time_secs(G1GCPhaseTimes::CodeRoots, G1GCPhaseTimes::ObjCopy, worker_i, pss->closures()->trim_time_seconds());
434 }
435
436 // Closure used for updating rem sets. Only called during an evacuation pause.
437 class G1RefineCardClosure: public CardTableEntryClosure {
438 G1RemSet* _g1rs;
439 G1ScanObjsDuringUpdateRSClosure* _update_rs_cl;
440
441 size_t _cards_scanned;
442 size_t _cards_skipped;
443 public:
444 G1RefineCardClosure(G1CollectedHeap* g1h, G1ScanObjsDuringUpdateRSClosure* update_rs_cl) :
445 _g1rs(g1h->g1_rem_set()), _update_rs_cl(update_rs_cl), _cards_scanned(0), _cards_skipped(0)
446 {}
447
448 bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
449 // The only time we care about recording cards that
450 // contain references that point into the collection set
451 // is during RSet updating within an evacuation pause.
452 // In this case worker_i should be the id of a GC worker thread.
453 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
454
455 bool card_scanned = _g1rs->refine_card_during_gc(card_ptr, _update_rs_cl);
456
457 if (card_scanned) {
458 _update_rs_cl->trim_queue_partially();
459 _cards_scanned++;
460 } else {
461 _cards_skipped++;
462 }
463 return true;
464 }
465
466 size_t cards_scanned() const { return _cards_scanned; }
467 size_t cards_skipped() const { return _cards_skipped; }
468 };
469
470 void G1RemSet::update_rem_set(G1ParScanThreadState* pss, uint worker_i) {
471 G1GCPhaseTimes* p = _g1p->phase_times();
472 double scan_hcc_trim_queue_time = 0.0;
473
474 G1ScanObjsDuringUpdateRSClosure update_rs_cl(_g1h, pss, worker_i);
475 G1RefineCardClosure refine_card_cl(_g1h, &update_rs_cl);
476
477 {
478 G1GCParPhaseTimesTracker x(p, G1GCPhaseTimes::UpdateRS, worker_i);
479 if (G1HotCardCache::default_use_cache()) {
480 {
481 // Apply the closure to the entries of the hot card cache.
482 G1GCParPhaseTimesTracker y(p, G1GCPhaseTimes::ScanHCC, worker_i);
483 _g1h->iterate_hcc_closure(&refine_card_cl, worker_i);
484 }
485 scan_hcc_trim_queue_time = TicksToTimeHelper::seconds(update_rs_cl.trim_ticks_and_reset());
486 p->move_time_secs(G1GCPhaseTimes::ScanHCC, G1GCPhaseTimes::ObjCopy, worker_i, scan_hcc_trim_queue_time);
487 }
488 // Apply the closure to all remaining log entries.
489 _g1h->iterate_dirty_card_closure(&refine_card_cl, worker_i);
490 }
491 double update_rs_trim_queue_time = TicksToTimeHelper::seconds(update_rs_cl.trim_ticks_and_reset());
492
493 p->move_time_secs(G1GCPhaseTimes::UpdateRS, G1GCPhaseTimes::ObjCopy, worker_i, update_rs_trim_queue_time + scan_hcc_trim_queue_time);
494
495 p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_scanned(), G1GCPhaseTimes::UpdateRSScannedCards);
496 p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_skipped(), G1GCPhaseTimes::UpdateRSSkippedCards);
497 }
498
499 void G1RemSet::cleanupHRRS() {
500 HeapRegionRemSet::cleanup();
501 }
502
503 void G1RemSet::oops_into_collection_set_do(G1ParScanThreadState* pss, uint worker_i) {
504 update_rem_set(pss, worker_i);
505 scan_rem_set(pss, worker_i);;
506 }
507
508 void G1RemSet::prepare_for_oops_into_collection_set_do() {
509 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
510 dcqs.concatenate_logs();
511
512 _scan_state->reset();
513 }
|
289 _prev_period_summary() {
290 }
291
292 G1RemSet::~G1RemSet() {
293 if (_scan_state != NULL) {
294 delete _scan_state;
295 }
296 }
297
298 uint G1RemSet::num_par_rem_sets() {
299 return DirtyCardQueueSet::num_par_ids() + G1ConcurrentRefine::max_num_threads() + MAX2(ConcGCThreads, ParallelGCThreads);
300 }
301
302 void G1RemSet::initialize(size_t capacity, uint max_regions) {
303 G1FromCardCache::initialize(num_par_rem_sets(), max_regions);
304 _scan_state->initialize(max_regions);
305 }
306
307 G1ScanRSForRegionClosure::G1ScanRSForRegionClosure(G1RemSetScanState* scan_state,
308 G1ScanObjsDuringScanRSClosure* scan_obj_on_card,
309 G1ParScanThreadState* pss,
310 uint worker_i) :
311 _g1h(G1CollectedHeap::heap()),
312 _ct(_g1h->card_table()),
313 _pss(pss),
314 _scan_objs_on_card_cl(scan_obj_on_card),
315 _scan_state(scan_state),
316 _worker_i(worker_i),
317 _cards_claimed(0),
318 _cards_scanned(0),
319 _cards_skipped(0),
320 _rem_set_root_scan_time(),
321 _rem_set_trim_partially_time(),
322 _strong_code_root_scan_time(),
323 _strong_code_trim_partially_time() {
324 }
325
326 void G1ScanRSForRegionClosure::claim_card(size_t card_index, const uint region_idx_for_card){
327 _ct->set_card_claimed(card_index);
328 _scan_state->add_dirty_region(region_idx_for_card);
329 }
330
331 void G1ScanRSForRegionClosure::scan_card(MemRegion mr, uint region_idx_for_card) {
332 HeapRegion* const card_region = _g1h->region_at(region_idx_for_card);
333 _scan_objs_on_card_cl->set_region(card_region);
334 card_region->oops_on_card_seq_iterate_careful<true>(mr, _scan_objs_on_card_cl);
335 _scan_objs_on_card_cl->trim_queue_partially();
336 _cards_scanned++;
337 }
338
339 void G1ScanRSForRegionClosure::scan_rem_set_roots(HeapRegion* r) {
340 uint const region_idx = r->hrm_index();
341
342 if (_scan_state->claim_iter(region_idx)) {
343 // If we ever free the collection set concurrently, we should also
344 // clear the card table concurrently therefore we won't need to
345 // add regions of the collection set to the dirty cards region.
346 _scan_state->add_dirty_region(region_idx);
347 }
348
349 // We claim cards in blocks so as to reduce the contention.
350 size_t const block_size = G1RSetScanBlockSize;
351
352 HeapRegionRemSetIterator iter(r->rem_set());
353 size_t card_index;
354
355 size_t claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
356 for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
357 if (current_card >= claimed_card_block + block_size) {
358 claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
359 }
360 if (current_card < claimed_card_block) {
361 _cards_skipped++;
373
374 assert(_g1h->region_at(region_idx_for_card)->is_in_reserved(card_start),
375 "Card start " PTR_FORMAT " to scan outside of region %u", p2i(card_start), _g1h->region_at(region_idx_for_card)->hrm_index());
376 HeapWord* const top = _scan_state->scan_top(region_idx_for_card);
377 if (card_start >= top) {
378 continue;
379 }
380
381 // We claim lazily (so races are possible but they're benign), which reduces the
382 // number of duplicate scans (the rsets of the regions in the cset can intersect).
383 // Claim the card after checking bounds above: the remembered set may contain
384 // random cards into current survivor, and we would then have an incorrectly
385 // claimed card in survivor space. Card table clear does not reset the card table
386 // of survivor space regions.
387 claim_card(card_index, region_idx_for_card);
388
389 MemRegion const mr(card_start, MIN2(card_start + BOTConstants::N_words, top));
390
391 scan_card(mr, region_idx_for_card);
392 }
393 }
394
395 void G1ScanRSForRegionClosure::scan_strong_code_roots(HeapRegion* r) {
396 Ticks const scan_start = Ticks::now();
397 r->strong_code_roots_do(_pss->closures()->weak_codeblobs());
398 _strong_code_root_scan_time += (Ticks::now() - scan_start);
399 }
400
401 bool G1ScanRSForRegionClosure::do_heap_region(HeapRegion* r) {
402 assert(r->in_collection_set(),
403 "Should only be called on elements of the collection set but region %u is not.",
404 r->hrm_index());
405 uint const region_idx = r->hrm_index();
406
407 // Do an early out if we know we are complete.
408 if (_scan_state->iter_is_complete(region_idx)) {
409 return false;
410 }
411
412 {
413 Ticks const start = Ticks::now();
414 scan_rem_set_roots(r);
415 Tickspan const trim_partially_time = _pss->trim_ticks_and_reset();
416 _rem_set_root_scan_time += (Ticks::now() - start) - trim_partially_time;
417 _rem_set_trim_partially_time += trim_partially_time;
418 }
419
420 if (_scan_state->set_iter_complete(region_idx)) {
421 Ticks const start = Ticks::now();
422 // Scan the strong code root list attached to the current region
423 scan_strong_code_roots(r);
424 Tickspan const trim_partially_time = _pss->trim_ticks_and_reset();
425 _strong_code_root_scan_time += (Ticks::now() - start) - trim_partially_time;
426 _strong_code_trim_partially_time += trim_partially_time;
427 }
428 return false;
429 }
430
431 void G1RemSet::scan_rem_set(G1ParScanThreadState* pss, uint worker_i) {
432 G1ScanObjsDuringScanRSClosure scan_cl(_g1h, pss);
433 G1ScanRSForRegionClosure cl(_scan_state, &scan_cl, pss, worker_i);
434 _g1h->collection_set_iterate_from(&cl, worker_i);
435
436 G1GCPhaseTimes* p = _g1p->phase_times();
437
438 p->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, TicksToTimeHelper::seconds(cl.rem_set_root_scan_time()));
439 p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, TicksToTimeHelper::seconds(cl.rem_set_trim_partially_time()));
440
441 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_scanned(), G1GCPhaseTimes::ScanRSScannedCards);
442 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_claimed(), G1GCPhaseTimes::ScanRSClaimedCards);
443 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_skipped(), G1GCPhaseTimes::ScanRSSkippedCards);
444
445 p->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, TicksToTimeHelper::seconds(cl.strong_code_root_scan_time()));
446 p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, TicksToTimeHelper::seconds(cl.strong_code_root_trim_partially_time()));
447 }
448
449 // Closure used for updating rem sets. Only called during an evacuation pause.
450 class G1RefineCardClosure: public CardTableEntryClosure {
451 G1RemSet* _g1rs;
452 G1ScanObjsDuringUpdateRSClosure* _update_rs_cl;
453
454 size_t _cards_scanned;
455 size_t _cards_skipped;
456 public:
457 G1RefineCardClosure(G1CollectedHeap* g1h, G1ScanObjsDuringUpdateRSClosure* update_rs_cl) :
458 _g1rs(g1h->g1_rem_set()), _update_rs_cl(update_rs_cl), _cards_scanned(0), _cards_skipped(0)
459 {}
460
461 bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
462 // The only time we care about recording cards that
463 // contain references that point into the collection set
464 // is during RSet updating within an evacuation pause.
465 // In this case worker_i should be the id of a GC worker thread.
466 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
467
468 bool card_scanned = _g1rs->refine_card_during_gc(card_ptr, _update_rs_cl);
469
470 if (card_scanned) {
471 _update_rs_cl->trim_queue_partially();
472 _cards_scanned++;
473 } else {
474 _cards_skipped++;
475 }
476 return true;
477 }
478
479 size_t cards_scanned() const { return _cards_scanned; }
480 size_t cards_skipped() const { return _cards_skipped; }
481 };
482
483 void G1RemSet::update_rem_set(G1ParScanThreadState* pss, uint worker_i) {
484 G1GCPhaseTimes* p = _g1p->phase_times();
485
486 // Apply closure to log entries in the HCC.
487 if (G1HotCardCache::default_use_cache()) {
488 {
489 G1GCParPhaseTimesTracker x(p, G1GCPhaseTimes::ScanHCC, worker_i);
490
491 G1ScanObjsDuringUpdateRSClosure scan_hcc_cl(_g1h, pss, worker_i);
492 G1RefineCardClosure refine_card_cl(_g1h, &scan_hcc_cl);
493
494 _g1h->iterate_hcc_closure(&refine_card_cl, worker_i);
495 }
496 double const scan_hcc_trim_queue_time = TicksToTimeHelper::seconds(pss->trim_ticks_and_reset());
497 p->move_time_secs(G1GCPhaseTimes::ScanHCC, G1GCPhaseTimes::ObjCopy, worker_i, scan_hcc_trim_queue_time);
498 }
499
500 // Now apply the closure to all remaining log entries.
501 G1ScanObjsDuringUpdateRSClosure update_rs_cl(_g1h, pss, worker_i);
502 G1RefineCardClosure refine_card_cl(_g1h, &update_rs_cl);
503 {
504 G1GCParPhaseTimesTracker x(p, G1GCPhaseTimes::UpdateRS, worker_i);
505 _g1h->iterate_dirty_card_closure(&refine_card_cl, worker_i);
506 }
507
508 double const update_rs_trim_queue_time = TicksToTimeHelper::seconds(pss->trim_ticks_and_reset());
509 p->move_time_secs(G1GCPhaseTimes::UpdateRS, G1GCPhaseTimes::ObjCopy, worker_i, update_rs_trim_queue_time);
510
511 p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_scanned(), G1GCPhaseTimes::UpdateRSScannedCards);
512 p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_skipped(), G1GCPhaseTimes::UpdateRSSkippedCards);
513 }
514
515 void G1RemSet::cleanupHRRS() {
516 HeapRegionRemSet::cleanup();
517 }
518
519 void G1RemSet::oops_into_collection_set_do(G1ParScanThreadState* pss, uint worker_i) {
520 update_rem_set(pss, worker_i);
521 scan_rem_set(pss, worker_i);;
522 }
523
524 void G1RemSet::prepare_for_oops_into_collection_set_do() {
525 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
526 dcqs.concatenate_logs();
527
528 _scan_state->reset();
529 }
|