< prev index next >

src/hotspot/share/gc/g1/g1RemSet.cpp

Print this page

        

@@ -186,11 +186,11 @@
   }
 
   void reset() {
     for (uint i = 0; i < _max_regions; i++) {
       _iter_states[i] = Unclaimed;
-      clear_scan_top(i);
+      _scan_top[i] = NULL;
     }
 
     G1ResetScanTopClosure cl(_scan_top);
     G1CollectedHeap::heap()->heap_region_iterate(&cl);
 

@@ -251,14 +251,10 @@
 
   HeapWord* scan_top(uint region_idx) const {
     return _scan_top[region_idx];
   }
 
-  void clear_scan_top(uint region_idx) {
-    _scan_top[region_idx] = NULL;
-  }
-
   // Clear the card table of "dirty" regions.
   void clear_card_table(WorkGang* workers) {
     if (_cur_dirty_region == 0) {
       return;
     }

@@ -306,241 +302,170 @@
 void G1RemSet::initialize(size_t capacity, uint max_regions) {
   G1FromCardCache::initialize(num_par_rem_sets(), max_regions);
   _scan_state->initialize(max_regions);
 }
 
-class G1ScanRSForRegionClosure : public HeapRegionClosure {
-  G1CollectedHeap* _g1h;
-  G1CardTable *_ct;
-
-  G1ParScanThreadState* _pss;
-  G1ScanCardClosure* _scan_objs_on_card_cl;
-
-  G1RemSetScanState* _scan_state;
-
-  G1GCPhaseTimes::GCParPhases _phase;
-
-  uint   _worker_i;
-
-  size_t _opt_refs_scanned;
-  size_t _opt_refs_memory_used;
-
-  size_t _cards_scanned;
-  size_t _cards_claimed;
-  size_t _cards_skipped;
-
-  Tickspan _rem_set_root_scan_time;
-  Tickspan _rem_set_trim_partially_time;
-
-  Tickspan _strong_code_root_scan_time;
-  Tickspan _strong_code_trim_partially_time;
-
-  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);
+G1ScanRSForRegionClosure::G1ScanRSForRegionClosure(G1RemSetScanState* scan_state,
+                                                   G1ScanObjsDuringScanRSClosure* 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),
+  _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() {
+}
+
+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);
+}
+
+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++;
+}
+
+void G1ScanRSForRegionClosure::scan_rem_set_roots(HeapRegion* r) {
+  EventGCPhaseParallel event;
+  uint const region_idx = r->hrm_index();
+
+  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 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++;
+  if (r->rem_set()->cardset_is_empty()) {
+    return;
   }
 
-  void scan_opt_rem_set_roots(HeapRegion* r) {
-    EventGCPhaseParallel event;
+  // We claim cards in blocks so as to reduce the contention.
+  size_t const block_size = G1RSetScanBlockSize;
 
-    G1OopStarChunkedList* opt_rem_set_list = _pss->oops_into_optional_region(r);
+  HeapRegionRemSetIterator iter(r->rem_set());
+  size_t card_index;
 
-    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));
-  }
-
-  void scan_rem_set_roots(HeapRegion* r) {
-    EventGCPhaseParallel event;
-    uint const region_idx = r->hrm_index();
-
-    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);
+  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 (r->rem_set()->cardset_is_empty()) {
-      return;
+    if (current_card < claimed_card_block) {
+      _cards_skipped++;
+      continue;
     }
+    _cards_claimed++;
 
-    // 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;
-
-    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);
+    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());
+    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 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;
-      }
-
-      // 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));
-  }
-
-  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);
+    HeapWord* const top = _scan_state->scan_top(region_idx_for_card);
+    if (card_start >= top) {
+      continue;
     }
 
-    // Do an early out if we know we are complete.
-    if (_scan_state->iter_is_complete(region_idx)) {
-      return false;
+    // 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;
     }
 
-    {
-      G1EvacPhaseWithTrimTimeTracker timer(_pss, _rem_set_root_scan_time, _rem_set_trim_partially_time);
-      scan_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);
 
-    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;
+    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));
+}
 
-  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; }
+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));
+}
 
-  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; }
+bool G1ScanRSForRegionClosure::do_heap_region(HeapRegion* r) {
+  assert(r->in_collection_set(),
+         "Should only be called on elements of the collection set but region %u is not.",
+         r->hrm_index());
+  uint const region_idx = r->hrm_index();
 
-  size_t cards_scanned() const { return _cards_scanned; }
-  size_t cards_claimed() const { return _cards_claimed; }
-  size_t cards_skipped() const { return _cards_skipped; }
+  // Do an early out if we know we are complete.
+  if (_scan_state->iter_is_complete(region_idx)) {
+    return false;
+  }
 
-  size_t opt_refs_scanned() const { return _opt_refs_scanned; }
-  size_t opt_refs_memory_used() const { return _opt_refs_memory_used; }
-};
+  {
+    G1EvacPhaseWithTrimTimeTracker timer(_pss, _rem_set_root_scan_time, _rem_set_trim_partially_time);
+    scan_rem_set_roots(r);
+  }
 
-void G1RemSet::scan_rem_set(G1ParScanThreadState* pss,
-                            uint worker_i,
-                            G1GCPhaseTimes::GCParPhases scan_phase,
-                            G1GCPhaseTimes::GCParPhases objcopy_phase,
-                            G1GCPhaseTimes::GCParPhases coderoots_phase) {
-  assert(pss->trim_ticks().value() == 0, "Queues must have been trimmed before entering.");
-
-  G1ScanCardClosure scan_cl(_g1h, pss);
-  G1ScanRSForRegionClosure cl(_scan_state, &scan_cl, pss, scan_phase, worker_i);
-  _g1h->collection_set_iterate_increment_from(&cl, worker_i);
+  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;
+}
+
+void G1RemSet::scan_rem_set(G1ParScanThreadState* pss, uint worker_i) {
+  G1ScanObjsDuringScanRSClosure scan_cl(_g1h, pss);
+  G1ScanRSForRegionClosure cl(_scan_state, &scan_cl, pss, G1GCPhaseTimes::ScanRS, worker_i);
+  _g1h->collection_set_iterate_from(&cl, worker_i);
 
   G1GCPhaseTimes* p = _g1p->phase_times();
 
-  p->record_or_add_time_secs(objcopy_phase, worker_i, cl.rem_set_trim_partially_time().seconds());
+  p->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, cl.rem_set_root_scan_time().seconds());
+  p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, cl.rem_set_trim_partially_time().seconds());
 
-  p->record_or_add_time_secs(scan_phase, worker_i, cl.rem_set_root_scan_time().seconds());
-  p->record_or_add_thread_work_item(scan_phase, worker_i, cl.cards_scanned(), G1GCPhaseTimes::ScanRSScannedCards);
-  p->record_or_add_thread_work_item(scan_phase, worker_i, cl.cards_claimed(), G1GCPhaseTimes::ScanRSClaimedCards);
-  p->record_or_add_thread_work_item(scan_phase, worker_i, cl.cards_skipped(), G1GCPhaseTimes::ScanRSSkippedCards);
-  // At this time we only record some metrics for the optional remembered set.
-  if (scan_phase == G1GCPhaseTimes::OptScanRS) {
-    p->record_or_add_thread_work_item(scan_phase, worker_i, cl.opt_refs_scanned(), G1GCPhaseTimes::ScanRSScannedOptRefs);
-    p->record_or_add_thread_work_item(scan_phase, worker_i, cl.opt_refs_memory_used(), G1GCPhaseTimes::ScanRSUsedMemory);
-  }
+  p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_scanned(), G1GCPhaseTimes::ScanRSScannedCards);
+  p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_claimed(), G1GCPhaseTimes::ScanRSClaimedCards);
+  p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_skipped(), G1GCPhaseTimes::ScanRSSkippedCards);
 
-  p->record_or_add_time_secs(coderoots_phase, worker_i, cl.strong_code_root_scan_time().seconds());
-  p->add_time_secs(objcopy_phase, worker_i, cl.strong_code_root_trim_partially_time().seconds());
+  p->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, cl.strong_code_root_scan_time().seconds());
+  p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, cl.strong_code_root_trim_partially_time().seconds());
 }
 
 // Closure used for updating rem sets. Only called during an evacuation pause.
 class G1RefineCardClosure: public G1CardTableEntryClosure {
   G1RemSet* _g1rs;
-  G1ScanCardClosure* _update_rs_cl;
+  G1ScanObjsDuringUpdateRSClosure* _update_rs_cl;
 
   size_t _cards_scanned;
   size_t _cards_skipped;
 public:
-  G1RefineCardClosure(G1CollectedHeap* g1h, G1ScanCardClosure* update_rs_cl) :
+  G1RefineCardClosure(G1CollectedHeap* g1h, G1ScanObjsDuringUpdateRSClosure* update_rs_cl) :
     _g1rs(g1h->rem_set()), _update_rs_cl(update_rs_cl), _cards_scanned(0), _cards_skipped(0)
   {}
 
   bool do_card_ptr(CardValue* card_ptr, uint worker_i) {
     // The only time we care about recording cards that

@@ -569,38 +494,39 @@
 
   // Apply closure to log entries in the HCC.
   if (G1HotCardCache::default_use_cache()) {
     G1EvacPhaseTimesTracker x(p, pss, G1GCPhaseTimes::ScanHCC, worker_i);
 
-    G1ScanCardClosure scan_hcc_cl(_g1h, pss);
+    G1ScanObjsDuringUpdateRSClosure scan_hcc_cl(_g1h, pss);
     G1RefineCardClosure refine_card_cl(_g1h, &scan_hcc_cl);
     _g1h->iterate_hcc_closure(&refine_card_cl, worker_i);
   }
 
   // Now apply the closure to all remaining log entries.
   {
     G1EvacPhaseTimesTracker x(p, pss, G1GCPhaseTimes::UpdateRS, worker_i);
 
-    G1ScanCardClosure update_rs_cl(_g1h, pss);
+    G1ScanObjsDuringUpdateRSClosure update_rs_cl(_g1h, pss);
     G1RefineCardClosure refine_card_cl(_g1h, &update_rs_cl);
     _g1h->iterate_dirty_card_closure(&refine_card_cl, worker_i);
 
     p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_scanned(), G1GCPhaseTimes::UpdateRSScannedCards);
     p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_skipped(), G1GCPhaseTimes::UpdateRSSkippedCards);
   }
 }
 
-void G1RemSet::prepare_for_scan_rem_set() {
-  G1BarrierSet::dirty_card_queue_set().concatenate_logs();
-  _scan_state->reset();
+void G1RemSet::oops_into_collection_set_do(G1ParScanThreadState* pss, uint worker_i) {
+  update_rem_set(pss, worker_i);
+  scan_rem_set(pss, worker_i);;
 }
 
-void G1RemSet::prepare_for_scan_rem_set(uint region_idx) {
-  _scan_state->clear_scan_top(region_idx);
+void G1RemSet::prepare_for_oops_into_collection_set_do() {
+  G1BarrierSet::dirty_card_queue_set().concatenate_logs();
+  _scan_state->reset();
 }
 
-void G1RemSet::cleanup_after_scan_rem_set() {
+void G1RemSet::cleanup_after_oops_into_collection_set_do() {
   G1GCPhaseTimes* phase_times = _g1h->phase_times();
 
   // Set all cards back to clean.
   double start = os::elapsedTime();
   _scan_state->clear_card_table(_g1h->workers());

@@ -758,11 +684,11 @@
   *card_ptr = G1CardTable::dirty_card_val();
   G1BarrierSet::shared_dirty_card_queue().enqueue(card_ptr);
 }
 
 bool G1RemSet::refine_card_during_gc(CardValue* card_ptr,
-                                     G1ScanCardClosure* update_rs_cl) {
+                                     G1ScanObjsDuringUpdateRSClosure* update_rs_cl) {
   assert(_g1h->is_gc_active(), "Only call during GC");
 
   // Construct the region representing the card.
   HeapWord* card_start = _ct->addr_for(card_ptr);
   // And find the region containing it.
< prev index next >