--- a/src/hotspot/share/gc/g1/g1RemSet.cpp Wed May 22 10:48:46 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp Wed May 22 11:19:14 2019 +0200
@@ -308,158 +308,198 @@
_scan_state->initialize(max_regions);
}
-G1ScanRSForRegionClosure::G1ScanRSForRegionClosure(G1RemSetScanState* scan_state,
- G1ScanCardClosure* scan_obj_on_card,
- G1ParScanThreadState* pss,
- G1GCPhaseTimes::GCParPhases phase,
- uint worker_i) :
- _g1h(G1CollectedHeap::heap()),
- _ct(_g1h->card_table()),
- _pss(pss),
- _scan_objs_on_card_cl(scan_obj_on_card),
- _scan_state(scan_state),
- _phase(phase),
- _worker_i(worker_i),
- _opt_refs_scanned(0),
- _opt_refs_memory_used(0),
- _cards_scanned(0),
- _cards_claimed(0),
- _cards_skipped(0),
- _rem_set_root_scan_time(),
- _rem_set_trim_partially_time(),
- _strong_code_root_scan_time(),
- _strong_code_trim_partially_time() {
-}
+class G1ScanRSForRegionClosure : public HeapRegionClosure {
+ G1CollectedHeap* _g1h;
+ G1CardTable *_ct;
-void G1ScanRSForRegionClosure::claim_card(size_t card_index, const uint region_idx_for_card){
- _ct->set_card_claimed(card_index);
- _scan_state->add_dirty_region(region_idx_for_card);
-}
+ G1ParScanThreadState* _pss;
+ G1ScanCardClosure* _scan_objs_on_card_cl;
+
+ G1RemSetScanState* _scan_state;
+
+ G1GCPhaseTimes::GCParPhases _phase;
+
+ uint _worker_i;
-void G1ScanRSForRegionClosure::scan_card(MemRegion mr, uint region_idx_for_card) {
- HeapRegion* const card_region = _g1h->region_at(region_idx_for_card);
- assert(!card_region->is_young(), "Should not scan card in young region %u", region_idx_for_card);
- card_region->oops_on_card_seq_iterate_careful<true>(mr, _scan_objs_on_card_cl);
- _scan_objs_on_card_cl->trim_queue_partially();
- _cards_scanned++;
-}
+ size_t _opt_refs_scanned;
+ size_t _opt_refs_memory_used;
-void G1ScanRSForRegionClosure::scan_opt_rem_set_roots(HeapRegion* r) {
- EventGCPhaseParallel event;
-
- G1OopStarChunkedList* opt_rem_set_list = _pss->oops_into_optional_region(r);
+ size_t _cards_scanned;
+ size_t _cards_claimed;
+ size_t _cards_skipped;
- G1ScanCardClosure scan_cl(_g1h, _pss);
- G1ScanRSForOptionalClosure cl(_g1h, &scan_cl);
- _opt_refs_scanned += opt_rem_set_list->oops_do(&cl, _pss->closures()->raw_strong_oops());
- _opt_refs_memory_used += opt_rem_set_list->used_memory();
-
- event.commit(GCId::current(), _worker_i, G1GCPhaseTimes::phase_name(_phase));
-}
+ Tickspan _rem_set_root_scan_time;
+ Tickspan _rem_set_trim_partially_time;
-void G1ScanRSForRegionClosure::scan_rem_set_roots(HeapRegion* r) {
- EventGCPhaseParallel event;
- uint const region_idx = r->hrm_index();
+ Tickspan _strong_code_root_scan_time;
+ Tickspan _strong_code_trim_partially_time;
- if (_scan_state->claim_iter(region_idx)) {
- // If we ever free the collection set concurrently, we should also
- // clear the card table concurrently therefore we won't need to
- // add regions of the collection set to the dirty cards region.
- _scan_state->add_dirty_region(region_idx);
+ void claim_card(size_t card_index, const uint region_idx_for_card) {
+ _ct->set_card_claimed(card_index);
+ _scan_state->add_dirty_region(region_idx_for_card);
}
- if (r->rem_set()->cardset_is_empty()) {
- return;
+ void scan_card(MemRegion mr, uint region_idx_for_card) {
+ HeapRegion* const card_region = _g1h->region_at(region_idx_for_card);
+ assert(!card_region->is_young(), "Should not scan card in young region %u", region_idx_for_card);
+ card_region->oops_on_card_seq_iterate_careful<true>(mr, _scan_objs_on_card_cl);
+ _scan_objs_on_card_cl->trim_queue_partially();
+ _cards_scanned++;
+ }
+
+ void scan_opt_rem_set_roots(HeapRegion* r) {
+ EventGCPhaseParallel event;
+
+ G1OopStarChunkedList* opt_rem_set_list = _pss->oops_into_optional_region(r);
+
+ G1ScanCardClosure scan_cl(_g1h, _pss);
+ G1ScanRSForOptionalClosure cl(_g1h, &scan_cl);
+ _opt_refs_scanned += opt_rem_set_list->oops_do(&cl, _pss->closures()->raw_strong_oops());
+ _opt_refs_memory_used += opt_rem_set_list->used_memory();
+
+ event.commit(GCId::current(), _worker_i, G1GCPhaseTimes::phase_name(_phase));
}
- // We claim cards in blocks so as to reduce the contention.
- size_t const block_size = G1RSetScanBlockSize;
-
- HeapRegionRemSetIterator iter(r->rem_set());
- size_t card_index;
+ void scan_rem_set_roots(HeapRegion* r) {
+ EventGCPhaseParallel event;
+ uint const region_idx = r->hrm_index();
- size_t claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
- for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
- if (current_card >= claimed_card_block + block_size) {
- claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
- }
- if (current_card < claimed_card_block) {
- _cards_skipped++;
- continue;
- }
- _cards_claimed++;
-
- HeapWord* const card_start = _g1h->bot()->address_for_index_raw(card_index);
- uint const region_idx_for_card = _g1h->addr_to_region(card_start);
-
-#ifdef ASSERT
- HeapRegion* hr = _g1h->region_at_or_null(region_idx_for_card);
- assert(hr == NULL || hr->is_in_reserved(card_start),
- "Card start " PTR_FORMAT " to scan outside of region %u", p2i(card_start), _g1h->region_at(region_idx_for_card)->hrm_index());
-#endif
- HeapWord* const top = _scan_state->scan_top(region_idx_for_card);
- if (card_start >= top) {
- continue;
+ if (_scan_state->claim_iter(region_idx)) {
+ // If we ever free the collection set concurrently, we should also
+ // clear the card table concurrently therefore we won't need to
+ // add regions of the collection set to the dirty cards region.
+ _scan_state->add_dirty_region(region_idx);
}
- // If the card is dirty, then G1 will scan it during Update RS.
- if (_ct->is_card_claimed(card_index) || _ct->is_card_dirty(card_index)) {
- continue;
+ if (r->rem_set()->cardset_is_empty()) {
+ return;
}
- // We claim lazily (so races are possible but they're benign), which reduces the
- // number of duplicate scans (the rsets of the regions in the cset can intersect).
- // Claim the card after checking bounds above: the remembered set may contain
- // random cards into current survivor, and we would then have an incorrectly
- // claimed card in survivor space. Card table clear does not reset the card table
- // of survivor space regions.
- claim_card(card_index, region_idx_for_card);
+ // We claim cards in blocks so as to reduce the contention.
+ size_t const block_size = G1RSetScanBlockSize;
+
+ HeapRegionRemSetIterator iter(r->rem_set());
+ size_t card_index;
- MemRegion const mr(card_start, MIN2(card_start + BOTConstants::N_words, top));
+ size_t claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
+ for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
+ if (current_card >= claimed_card_block + block_size) {
+ claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
+ }
+ if (current_card < claimed_card_block) {
+ _cards_skipped++;
+ continue;
+ }
+ _cards_claimed++;
- scan_card(mr, region_idx_for_card);
- }
- event.commit(GCId::current(), _worker_i, G1GCPhaseTimes::phase_name(_phase));
-}
+ HeapWord* const card_start = _g1h->bot()->address_for_index_raw(card_index);
+ uint const region_idx_for_card = _g1h->addr_to_region(card_start);
-void G1ScanRSForRegionClosure::scan_strong_code_roots(HeapRegion* r) {
- EventGCPhaseParallel event;
- // We pass a weak code blobs closure to the remembered set scanning because we want to avoid
- // treating the nmethods visited to act as roots for concurrent marking.
- // We only want to make sure that the oops in the nmethods are adjusted with regard to the
- // objects copied by the current evacuation.
- r->strong_code_roots_do(_pss->closures()->weak_codeblobs());
- event.commit(GCId::current(), _worker_i, G1GCPhaseTimes::phase_name(G1GCPhaseTimes::CodeRoots));
-}
+#ifdef ASSERT
+ HeapRegion* hr = _g1h->region_at_or_null(region_idx_for_card);
+ assert(hr == NULL || hr->is_in_reserved(card_start),
+ "Card start " PTR_FORMAT " to scan outside of region %u", p2i(card_start), _g1h->region_at(region_idx_for_card)->hrm_index());
+#endif
+ HeapWord* const top = _scan_state->scan_top(region_idx_for_card);
+ if (card_start >= top) {
+ continue;
+ }
-bool G1ScanRSForRegionClosure::do_heap_region(HeapRegion* r) {
- assert(r->in_collection_set(), "Region %u is not in the collection set.", r->hrm_index());
- uint const region_idx = r->hrm_index();
+ // If the card is dirty, then G1 will scan it during Update RS.
+ if (_ct->is_card_claimed(card_index) || _ct->is_card_dirty(card_index)) {
+ continue;
+ }
- // The individual references for the optional remembered set are per-worker, so we
- // always need to scan them.
- if (r->has_index_in_opt_cset()) {
- G1EvacPhaseWithTrimTimeTracker timer(_pss, _rem_set_root_scan_time, _rem_set_trim_partially_time);
- scan_opt_rem_set_roots(r);
+ // We claim lazily (so races are possible but they're benign), which reduces the
+ // number of duplicate scans (the rsets of the regions in the cset can intersect).
+ // Claim the card after checking bounds above: the remembered set may contain
+ // random cards into current survivor, and we would then have an incorrectly
+ // claimed card in survivor space. Card table clear does not reset the card table
+ // of survivor space regions.
+ claim_card(card_index, region_idx_for_card);
+
+ MemRegion const mr(card_start, MIN2(card_start + BOTConstants::N_words, top));
+
+ scan_card(mr, region_idx_for_card);
+ }
+ event.commit(GCId::current(), _worker_i, G1GCPhaseTimes::phase_name(_phase));
}
- // Do an early out if we know we are complete.
- if (_scan_state->iter_is_complete(region_idx)) {
+ void scan_strong_code_roots(HeapRegion* r) {
+ EventGCPhaseParallel event;
+ // We pass a weak code blobs closure to the remembered set scanning because we want to avoid
+ // treating the nmethods visited to act as roots for concurrent marking.
+ // We only want to make sure that the oops in the nmethods are adjusted with regard to the
+ // objects copied by the current evacuation.
+ r->strong_code_roots_do(_pss->closures()->weak_codeblobs());
+ event.commit(GCId::current(), _worker_i, G1GCPhaseTimes::phase_name(G1GCPhaseTimes::CodeRoots));
+ }
+
+public:
+ G1ScanRSForRegionClosure(G1RemSetScanState* scan_state,
+ G1ScanCardClosure* scan_obj_on_card,
+ G1ParScanThreadState* pss,
+ G1GCPhaseTimes::GCParPhases phase,
+ uint worker_i) :
+ _g1h(G1CollectedHeap::heap()),
+ _ct(_g1h->card_table()),
+ _pss(pss),
+ _scan_objs_on_card_cl(scan_obj_on_card),
+ _scan_state(scan_state),
+ _phase(phase),
+ _worker_i(worker_i),
+ _opt_refs_scanned(0),
+ _opt_refs_memory_used(0),
+ _cards_scanned(0),
+ _cards_claimed(0),
+ _cards_skipped(0),
+ _rem_set_root_scan_time(),
+ _rem_set_trim_partially_time(),
+ _strong_code_root_scan_time(),
+ _strong_code_trim_partially_time() { }
+
+ bool do_heap_region(HeapRegion* r) {
+ assert(r->in_collection_set(), "Region %u is not in the collection set.", r->hrm_index());
+ uint const region_idx = r->hrm_index();
+
+ // The individual references for the optional remembered set are per-worker, so we
+ // always need to scan them.
+ if (r->has_index_in_opt_cset()) {
+ G1EvacPhaseWithTrimTimeTracker timer(_pss, _rem_set_root_scan_time, _rem_set_trim_partially_time);
+ scan_opt_rem_set_roots(r);
+ }
+
+ // Do an early out if we know we are complete.
+ if (_scan_state->iter_is_complete(region_idx)) {
+ return false;
+ }
+
+ {
+ G1EvacPhaseWithTrimTimeTracker timer(_pss, _rem_set_root_scan_time, _rem_set_trim_partially_time);
+ scan_rem_set_roots(r);
+ }
+
+ if (_scan_state->set_iter_complete(region_idx)) {
+ G1EvacPhaseWithTrimTimeTracker timer(_pss, _strong_code_root_scan_time, _strong_code_trim_partially_time);
+ // Scan the strong code root list attached to the current region
+ scan_strong_code_roots(r);
+ }
return false;
}
- {
- G1EvacPhaseWithTrimTimeTracker timer(_pss, _rem_set_root_scan_time, _rem_set_trim_partially_time);
- scan_rem_set_roots(r);
- }
+ Tickspan rem_set_root_scan_time() const { return _rem_set_root_scan_time; }
+ Tickspan rem_set_trim_partially_time() const { return _rem_set_trim_partially_time; }
+
+ Tickspan strong_code_root_scan_time() const { return _strong_code_root_scan_time; }
+ Tickspan strong_code_root_trim_partially_time() const { return _strong_code_trim_partially_time; }
- if (_scan_state->set_iter_complete(region_idx)) {
- G1EvacPhaseWithTrimTimeTracker timer(_pss, _strong_code_root_scan_time, _strong_code_trim_partially_time);
- // Scan the strong code root list attached to the current region
- scan_strong_code_roots(r);
- }
- return false;
-}
+ size_t cards_scanned() const { return _cards_scanned; }
+ size_t cards_claimed() const { return _cards_claimed; }
+ size_t cards_skipped() const { return _cards_skipped; }
+
+ size_t opt_refs_scanned() const { return _opt_refs_scanned; }
+ size_t opt_refs_memory_used() const { return _opt_refs_memory_used; }
+};
void G1RemSet::scan_rem_set(G1ParScanThreadState* pss,
uint worker_i,