src/hotspot/share/gc/g1/g1RemSet.cpp
changeset 54977 ab96027e99ed
parent 54934 39814e0a8964
child 55510 3e31a8beaae4
child 58678 9cf78a70fa4f
--- 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,