< prev index next >

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

Print this page
rev 55404 : 8226197: Reducing G1?s CPU cost with simplified write post-barrier and disabling concurrent refinement
Summary: A prototype to add a mode for G1 to use a simplified write post-barrier. Guarded by new flag G1FastWriteBarrier.

@@ -750,11 +750,13 @@
   }
 
   assert_heap_not_locked();
   if (result != NULL) {
     assert(*actual_word_size != 0, "Actual size must have been set here");
+    if (!G1FastWriteBarrier) {
     dirty_young_block(result, *actual_word_size);
+    }
   } else {
     *actual_word_size = 0;
   }
 
   return result;

@@ -1070,10 +1072,13 @@
   // Post collection state updates.
   MetaspaceGC::compute_new_size();
 }
 
 void G1CollectedHeap::abort_refinement() {
+  if (G1FastWriteBarrier) {
+    return;
+  }
   if (_hot_card_cache->use_cache()) {
     _hot_card_cache->reset_hot_cache();
   }
 
   // Discard all remembered set updates.

@@ -2725,11 +2730,13 @@
           CardTable::CardValue* card_ptr = ct->byte_for_index(card_index);
           // The remembered set might contain references to already freed
           // regions. Filter out such entries to avoid failing card table
           // verification.
           if (g1h->is_in(ct->addr_for(card_ptr))) {
-            if (*card_ptr != G1CardTable::dirty_card_val()) {
+            if (G1FastWriteBarrier) {
+              *card_ptr = G1CardTable::dirty_card_val();
+            } else if (*card_ptr != G1CardTable::dirty_card_val()) {
               *card_ptr = G1CardTable::dirty_card_val();
               _dcq.enqueue(card_ptr);
             }
           }
         }

@@ -2987,11 +2994,16 @@
   print_heap_before_gc();
   print_heap_regions();
   trace_heap_before_gc(_gc_tracer_stw);
 
   _verifier->verify_region_sets_optional();
+  // With G1FastWriteBarrier, cards for young regions can become dirty,
+  // and the collection set only contains young regions at this point.
+  // So it doesn't make sense to verify the cards for young regions.
+  if (!G1FastWriteBarrier) {
   _verifier->verify_dirty_young_regions();
+  }
 
   // We should not be doing initial mark unless the conc mark thread is running
   if (!_cm_thread->should_terminate()) {
     // This call will decide whether this pause is an initial-mark
     // pause. If it is, in_initial_mark_gc() will return true

@@ -3286,12 +3298,16 @@
 
   G1RedirtyLoggedCardsTask redirty_task(&dirty_card_queue_set(), this);
   dirty_card_queue_set().reset_for_par_iteration();
   workers()->run_task(&redirty_task);
 
+  if (G1FastWriteBarrier) {
+    dirty_card_queue_set().abandon_completed_buffers();
+  } else {
   G1DirtyCardQueueSet& dcq = G1BarrierSet::dirty_card_queue_set();
   dcq.merge_bufferlists(&dirty_card_queue_set());
+  }
   assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed");
 
   phase_times()->record_redirty_logged_cards_time_ms((os::elapsedTime() - redirty_logged_cards_start) * 1000.0);
 }
 

@@ -3616,10 +3632,12 @@
 
   // Should G1EvacuationFailureALot be in effect for this GC?
   NOT_PRODUCT(set_evacuation_failure_alot_for_current_gc();)
 
   assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty");
+  assert(!G1FastWriteBarrier || G1BarrierSet::dirty_card_queue_set().completed_buffers_num() == 0,
+         "Should be empty");
 }
 
 class G1EvacuateRegionsBaseTask : public AbstractGangTask {
 protected:
   G1CollectedHeap* _g1h;

@@ -3692,14 +3710,19 @@
   }
 };
 
 class G1EvacuateRegionsTask : public G1EvacuateRegionsBaseTask {
   G1RootProcessor* _root_processor;
+  HeapRegionClaimer _card_table_hr_claimer;
 
   void scan_roots(G1ParScanThreadState* pss, uint worker_id) {
     _root_processor->evacuate_roots(pss, worker_id);
+    if (G1FastWriteBarrier) {
+      _g1h->rem_set()->process_card_table(pss, worker_id, &_card_table_hr_claimer);
+    } else {
     _g1h->rem_set()->update_rem_set(pss, worker_id);
+    }
     _g1h->rem_set()->scan_rem_set(pss, worker_id, G1GCPhaseTimes::ScanRS, G1GCPhaseTimes::ObjCopy, G1GCPhaseTimes::CodeRoots);
   }
 
   void evacuate_live_objects(G1ParScanThreadState* pss, uint worker_id) {
     G1EvacuateRegionsBaseTask::evacuate_live_objects(pss, worker_id, G1GCPhaseTimes::ObjCopy, G1GCPhaseTimes::Termination);

@@ -3718,11 +3741,12 @@
                         G1ParScanThreadStateSet* per_thread_states,
                         RefToScanQueueSet* task_queues,
                         G1RootProcessor* root_processor,
                         uint num_workers) :
     G1EvacuateRegionsBaseTask("G1 Evacuate Regions", per_thread_states, task_queues, num_workers),
-    _root_processor(root_processor)
+    _root_processor(root_processor),
+    _card_table_hr_claimer(num_workers)
   { }
 };
 
 void G1CollectedHeap::evacuate_initial_collection_set(G1ParScanThreadStateSet* per_thread_states) {
   Tickspan task_time;
< prev index next >