--- 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