From 3a37b5d81c8c186fa895493ac86a654f30dbca20 Mon Sep 17 00:00:00 2001
From: Erik Helin <ehelin@openjdk.org>
Date: Wed, 29 Apr 2015 13:17:46 +0200
Subject: [PATCH] 8142402: G1 should not redirty cards in free regions

Reviewed-by: mgerdin, tschatzl
---
 .../src/share/vm/gc/g1/g1CollectedHeap.cpp    | 41 ++++++++++++++-----
 1 file changed, 31 insertions(+), 10 deletions(-)

diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
index cb5647260c6..f5f5d71575a 100644
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
@@ -112,18 +112,37 @@ public:
 
 class RedirtyLoggedCardTableEntryClosure : public CardTableEntryClosure {
  private:
-  size_t _num_processed;
+  size_t _num_dirtied;
+  G1CollectedHeap* _g1h;
+  G1SATBCardTableLoggingModRefBS* _g1_bs;
+
+  HeapRegion* region_for_card(jbyte* card_ptr) const {
+    return _g1h->heap_region_containing(_g1_bs->addr_for(card_ptr));
+  }
+
+  bool will_become_free(HeapRegion* hr) const {
+    // A region will be freed by free_collection_set if the region is in the
+    // collection set and has not had an evacuation failure.
+    return _g1h->is_in_cset(hr) && !hr->evacuation_failed();
+  }
 
  public:
-  RedirtyLoggedCardTableEntryClosure() : CardTableEntryClosure(), _num_processed(0) { }
+  RedirtyLoggedCardTableEntryClosure(G1CollectedHeap* g1h) : CardTableEntryClosure(),
+    _num_dirtied(0), _g1h(g1h), _g1_bs(g1h->g1_barrier_set()) { }
 
   bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
-    *card_ptr = CardTableModRefBS::dirty_card_val();
-    _num_processed++;
+    HeapRegion* hr = region_for_card(card_ptr);
+
+    // Should only dirty cards in regions that won't be freed.
+    if (!will_become_free(hr)) {
+      *card_ptr = CardTableModRefBS::dirty_card_val();
+      _num_dirtied++;
+    }
+
     return true;
   }
 
-  size_t num_processed() const { return _num_processed; }
+  size_t num_dirtied()   const { return _num_dirtied; }
 };
 
 
@@ -4619,24 +4638,26 @@ void G1CollectedHeap::unlink_string_and_symbol_table(BoolObjectClosure* is_alive
 class G1RedirtyLoggedCardsTask : public AbstractGangTask {
  private:
   DirtyCardQueueSet* _queue;
+  G1CollectedHeap* _g1h;
  public:
-  G1RedirtyLoggedCardsTask(DirtyCardQueueSet* queue) : AbstractGangTask("Redirty Cards"), _queue(queue) { }
+  G1RedirtyLoggedCardsTask(DirtyCardQueueSet* queue, G1CollectedHeap* g1h) : AbstractGangTask("Redirty Cards"),
+    _queue(queue), _g1h(g1h) { }
 
   virtual void work(uint worker_id) {
-    G1GCPhaseTimes* phase_times = G1CollectedHeap::heap()->g1_policy()->phase_times();
+    G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times();
     G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::RedirtyCards, worker_id);
 
-    RedirtyLoggedCardTableEntryClosure cl;
+    RedirtyLoggedCardTableEntryClosure cl(_g1h);
     _queue->par_apply_closure_to_all_completed_buffers(&cl);
 
-    phase_times->record_thread_work_item(G1GCPhaseTimes::RedirtyCards, worker_id, cl.num_processed());
+    phase_times->record_thread_work_item(G1GCPhaseTimes::RedirtyCards, worker_id, cl.num_dirtied());
   }
 };
 
 void G1CollectedHeap::redirty_logged_cards() {
   double redirty_logged_cards_start = os::elapsedTime();
 
-  G1RedirtyLoggedCardsTask redirty_task(&dirty_card_queue_set());
+  G1RedirtyLoggedCardsTask redirty_task(&dirty_card_queue_set(), this);
   dirty_card_queue_set().reset_for_par_iteration();
   workers()->run_task(&redirty_task);