src/hotspot/share/gc/g1/g1RemSet.cpp
changeset 54465 c4f16445675a
parent 54255 c81fbf340ceb
child 54843 25c329958c70
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp	Mon Apr 08 11:11:22 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp	Mon Apr 08 20:37:52 2019 +0200
@@ -316,6 +316,8 @@
   _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),
@@ -338,6 +340,19 @@
   _cards_scanned++;
 }
 
+void G1ScanRSForRegionClosure::scan_opt_rem_set_roots(HeapRegion* r) {
+  EventGCPhaseParallel event;
+
+  G1OopStarChunkedList* opt_rem_set_list = _pss->oops_into_optional_region(r);
+
+  G1ScanObjsDuringScanRSClosure scan_cl(_g1h, _pss);
+  G1ScanRSForOptionalClosure cl(&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 G1ScanRSForRegionClosure::scan_rem_set_roots(HeapRegion* r) {
   EventGCPhaseParallel event;
   uint const region_idx = r->hrm_index();
@@ -414,11 +429,16 @@
 }
 
 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());
+  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;
@@ -437,22 +457,33 @@
   return false;
 }
 
-void G1RemSet::scan_rem_set(G1ParScanThreadState* pss, uint worker_i) {
+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.");
+
   G1ScanObjsDuringScanRSClosure scan_cl(_g1h, pss);
-  G1ScanRSForRegionClosure cl(_scan_state, &scan_cl, pss, G1GCPhaseTimes::ScanRS, worker_i);
-  _g1h->collection_set_iterate_from(&cl, worker_i);
+  G1ScanRSForRegionClosure cl(_scan_state, &scan_cl, pss, scan_phase, worker_i);
+  _g1h->collection_set_iterate_increment_from(&cl, worker_i);
 
   G1GCPhaseTimes* p = _g1p->phase_times();
 
-  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(objcopy_phase, worker_i, cl.rem_set_trim_partially_time().seconds());
 
-  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(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_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());
+  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());
 }
 
 // Closure used for updating rem sets. Only called during an evacuation pause.
@@ -514,11 +545,6 @@
   }
 }
 
-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_oops_into_collection_set_do() {
   G1BarrierSet::dirty_card_queue_set().concatenate_logs();
   _scan_state->reset();