src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp
changeset 51485 0c7040d1d1ca
parent 50875 2217b2fc29ea
child 51489 b5abbca5b2dc
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp	Wed Aug 22 13:01:26 2018 +0200
+++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp	Wed Aug 22 13:06:33 2018 +0200
@@ -68,7 +68,26 @@
 }
 
 bool ZBarrierSetC2::is_gc_barrier_node(Node* node) const {
-  return node->is_LoadBarrier();
+  // 1. This step follows potential oop projections of a load barrier before expansion
+  if (node->is_Proj()) {
+    node = node->in(0);
+  }
+
+  // 2. This step checks for unexpanded load barriers
+  if (node->is_LoadBarrier()) {
+    return true;
+  }
+
+  // 3. This step checks for the phi corresponding to an optimized load barrier expansion
+  if (node->is_Phi()) {
+    PhiNode* phi = node->as_Phi();
+    Node* n = phi->in(1);
+    if (n != NULL && (n->is_LoadBarrierSlowReg() ||  n->is_LoadBarrierWeakSlowReg())) {
+      return true;
+    }
+  }
+
+  return false;
 }
 
 void ZBarrierSetC2::register_potential_barrier_node(Node* node) const {
@@ -637,7 +656,10 @@
     if (barrier == transformed_barrier) {
       kit->set_control(gvn.transform(new ProjNode(barrier, LoadBarrierNode::Control)));
     }
-    return gvn.transform(new ProjNode(transformed_barrier, LoadBarrierNode::Oop));
+    Node* result = gvn.transform(new ProjNode(transformed_barrier, LoadBarrierNode::Oop));
+    assert(is_gc_barrier_node(result), "sanity");
+    assert(step_over_gc_barrier(result) == val, "sanity");
+    return result;
   } else {
     return val;
   }
@@ -963,6 +985,9 @@
   traverse(preceding_barrier_node, result_region, result_phi, -1);
 #endif
 
+  assert(is_gc_barrier_node(result_phi), "sanity");
+  assert(step_over_gc_barrier(result_phi) == in_val, "sanity");
+
   return;
 }
 
@@ -1376,6 +1401,32 @@
   }
 }
 
+Node* ZBarrierSetC2::step_over_gc_barrier(Node* c) const {
+  Node* node = c;
+
+  // 1. This step follows potential oop projections of a load barrier before expansion
+  if (node->is_Proj()) {
+    node = node->in(0);
+  }
+
+  // 2. This step checks for unexpanded load barriers
+  if (node->is_LoadBarrier()) {
+    return node->in(LoadBarrierNode::Oop);
+  }
+
+  // 3. This step checks for the phi corresponding to an optimized load barrier expansion
+  if (node->is_Phi()) {
+    PhiNode* phi = node->as_Phi();
+    Node* n = phi->in(1);
+    if (n != NULL && (n->is_LoadBarrierSlowReg() ||  n->is_LoadBarrierWeakSlowReg())) {
+      assert(c == node, "projections from step 1 should only be seen before macro expansion");
+      return phi->in(2);
+    }
+  }
+
+  return c;
+}
+
 // == Verification ==
 
 #ifdef ASSERT