427 cl.strong_code_root_scan_time_sec(); |
427 cl.strong_code_root_scan_time_sec(); |
428 |
428 |
429 G1GCPhaseTimes* p = _g1p->phase_times(); |
429 G1GCPhaseTimes* p = _g1p->phase_times(); |
430 |
430 |
431 p->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, scan_rs_time_sec); |
431 p->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, scan_rs_time_sec); |
432 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_scanned(), G1GCPhaseTimes::ScannedCards); |
432 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_scanned(), G1GCPhaseTimes::ScanRSScannedCards); |
433 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_claimed(), G1GCPhaseTimes::ClaimedCards); |
433 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_claimed(), G1GCPhaseTimes::ScanRSClaimedCards); |
434 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_skipped(), G1GCPhaseTimes::SkippedCards); |
434 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_skipped(), G1GCPhaseTimes::ScanRSSkippedCards); |
435 |
435 |
436 p->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, cl.strong_code_root_scan_time_sec()); |
436 p->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, cl.strong_code_root_scan_time_sec()); |
437 } |
437 } |
438 |
438 |
439 // Closure used for updating rem sets. Only called during an evacuation pause. |
439 // Closure used for updating rem sets. Only called during an evacuation pause. |
440 class G1RefineCardClosure: public CardTableEntryClosure { |
440 class G1RefineCardClosure: public CardTableEntryClosure { |
441 G1RemSet* _g1rs; |
441 G1RemSet* _g1rs; |
442 G1ScanObjsDuringUpdateRSClosure* _update_rs_cl; |
442 G1ScanObjsDuringUpdateRSClosure* _update_rs_cl; |
|
443 |
|
444 size_t _cards_scanned; |
|
445 size_t _cards_skipped; |
443 public: |
446 public: |
444 G1RefineCardClosure(G1CollectedHeap* g1h, G1ScanObjsDuringUpdateRSClosure* update_rs_cl) : |
447 G1RefineCardClosure(G1CollectedHeap* g1h, G1ScanObjsDuringUpdateRSClosure* update_rs_cl) : |
445 _g1rs(g1h->g1_rem_set()), _update_rs_cl(update_rs_cl) |
448 _g1rs(g1h->g1_rem_set()), _update_rs_cl(update_rs_cl), _cards_scanned(0), _cards_skipped(0) |
446 {} |
449 {} |
447 |
450 |
448 bool do_card_ptr(jbyte* card_ptr, uint worker_i) { |
451 bool do_card_ptr(jbyte* card_ptr, uint worker_i) { |
449 // The only time we care about recording cards that |
452 // The only time we care about recording cards that |
450 // contain references that point into the collection set |
453 // contain references that point into the collection set |
451 // is during RSet updating within an evacuation pause. |
454 // is during RSet updating within an evacuation pause. |
452 // In this case worker_i should be the id of a GC worker thread. |
455 // 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"); |
456 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause"); |
454 |
457 |
455 _g1rs->refine_card_during_gc(card_ptr, _update_rs_cl); |
458 bool card_scanned = _g1rs->refine_card_during_gc(card_ptr, _update_rs_cl); |
|
459 |
|
460 if (card_scanned) { |
|
461 _cards_scanned++; |
|
462 } else { |
|
463 _cards_skipped++; |
|
464 } |
456 return true; |
465 return true; |
457 } |
466 } |
|
467 |
|
468 size_t cards_scanned() const { return _cards_scanned; } |
|
469 size_t cards_skipped() const { return _cards_skipped; } |
458 }; |
470 }; |
459 |
471 |
460 void G1RemSet::update_rem_set(G1ParScanThreadState* pss, uint worker_i) { |
472 void G1RemSet::update_rem_set(G1ParScanThreadState* pss, uint worker_i) { |
461 G1ScanObjsDuringUpdateRSClosure update_rs_cl(_g1, pss, worker_i); |
473 G1ScanObjsDuringUpdateRSClosure update_rs_cl(_g1, pss, worker_i); |
462 G1RefineCardClosure refine_card_cl(_g1, &update_rs_cl); |
474 G1RefineCardClosure refine_card_cl(_g1, &update_rs_cl); |
467 G1GCParPhaseTimesTracker y(_g1p->phase_times(), G1GCPhaseTimes::ScanHCC, worker_i); |
479 G1GCParPhaseTimesTracker y(_g1p->phase_times(), G1GCPhaseTimes::ScanHCC, worker_i); |
468 _g1->iterate_hcc_closure(&refine_card_cl, worker_i); |
480 _g1->iterate_hcc_closure(&refine_card_cl, worker_i); |
469 } |
481 } |
470 // Apply the closure to all remaining log entries. |
482 // Apply the closure to all remaining log entries. |
471 _g1->iterate_dirty_card_closure(&refine_card_cl, worker_i); |
483 _g1->iterate_dirty_card_closure(&refine_card_cl, worker_i); |
|
484 |
|
485 G1GCPhaseTimes* p = _g1p->phase_times(); |
|
486 p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_scanned(), G1GCPhaseTimes::UpdateRSScannedCards); |
|
487 p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_skipped(), G1GCPhaseTimes::UpdateRSSkippedCards); |
472 } |
488 } |
473 |
489 |
474 void G1RemSet::cleanupHRRS() { |
490 void G1RemSet::cleanupHRRS() { |
475 HeapRegionRemSet::cleanup(); |
491 HeapRegionRemSet::cleanup(); |
476 } |
492 } |
678 } else { |
694 } else { |
679 _num_conc_refined_cards++; // Unsynchronized update, only used for logging. |
695 _num_conc_refined_cards++; // Unsynchronized update, only used for logging. |
680 } |
696 } |
681 } |
697 } |
682 |
698 |
683 void G1RemSet::refine_card_during_gc(jbyte* card_ptr, |
699 bool G1RemSet::refine_card_during_gc(jbyte* card_ptr, |
684 G1ScanObjsDuringUpdateRSClosure* update_rs_cl) { |
700 G1ScanObjsDuringUpdateRSClosure* update_rs_cl) { |
685 assert(_g1->is_gc_active(), "Only call during GC"); |
701 assert(_g1->is_gc_active(), "Only call during GC"); |
686 |
702 |
687 check_card_ptr(card_ptr, _ct_bs); |
703 check_card_ptr(card_ptr, _ct_bs); |
688 |
704 |
689 // If the card is no longer dirty, nothing to do. This covers cards that were already |
705 // If the card is no longer dirty, nothing to do. This covers cards that were already |
690 // scanned as parts of the remembered sets. |
706 // scanned as parts of the remembered sets. |
691 if (*card_ptr != CardTableModRefBS::dirty_card_val()) { |
707 if (*card_ptr != CardTableModRefBS::dirty_card_val()) { |
692 return; |
708 return false; |
693 } |
709 } |
694 |
710 |
695 // We claim lazily (so races are possible but they're benign), which reduces the |
711 // We claim lazily (so races are possible but they're benign), which reduces the |
696 // number of potential duplicate scans (multiple threads may enqueue the same card twice). |
712 // number of potential duplicate scans (multiple threads may enqueue the same card twice). |
697 *card_ptr = CardTableModRefBS::clean_card_val() | CardTableModRefBS::claimed_card_val(); |
713 *card_ptr = CardTableModRefBS::clean_card_val() | CardTableModRefBS::claimed_card_val(); |
703 |
719 |
704 _scan_state->add_dirty_region(card_region_idx); |
720 _scan_state->add_dirty_region(card_region_idx); |
705 HeapWord* scan_limit = _scan_state->scan_top(card_region_idx); |
721 HeapWord* scan_limit = _scan_state->scan_top(card_region_idx); |
706 if (scan_limit <= card_start) { |
722 if (scan_limit <= card_start) { |
707 // If the card starts above the area in the region containing objects to scan, skip it. |
723 // If the card starts above the area in the region containing objects to scan, skip it. |
708 return; |
724 return false; |
709 } |
725 } |
710 |
726 |
711 // Don't use addr_for(card_ptr + 1) which can ask for |
727 // Don't use addr_for(card_ptr + 1) which can ask for |
712 // a card beyond the heap. |
728 // a card beyond the heap. |
713 HeapWord* card_end = card_start + CardTableModRefBS::card_size_in_words; |
729 HeapWord* card_end = card_start + CardTableModRefBS::card_size_in_words; |
716 |
732 |
717 HeapRegion* const card_region = _g1->region_at(card_region_idx); |
733 HeapRegion* const card_region = _g1->region_at(card_region_idx); |
718 update_rs_cl->set_region(card_region); |
734 update_rs_cl->set_region(card_region); |
719 bool card_processed = card_region->oops_on_card_seq_iterate_careful<true>(dirty_region, update_rs_cl); |
735 bool card_processed = card_region->oops_on_card_seq_iterate_careful<true>(dirty_region, update_rs_cl); |
720 assert(card_processed, "must be"); |
736 assert(card_processed, "must be"); |
|
737 return true; |
721 } |
738 } |
722 |
739 |
723 void G1RemSet::print_periodic_summary_info(const char* header, uint period_count) { |
740 void G1RemSet::print_periodic_summary_info(const char* header, uint period_count) { |
724 if ((G1SummarizeRSetStatsPeriod > 0) && log_is_enabled(Trace, gc, remset) && |
741 if ((G1SummarizeRSetStatsPeriod > 0) && log_is_enabled(Trace, gc, remset) && |
725 (period_count % G1SummarizeRSetStatsPeriod == 0)) { |
742 (period_count % G1SummarizeRSetStatsPeriod == 0)) { |