8226287: Make process_users_of_allocation handle gc barriers
authorneliasso
Mon, 01 Jul 2019 10:49:58 +0200
changeset 55536 8313c42345d5
parent 55535 df1925d3d409
child 55537 4309fedaf7dc
8226287: Make process_users_of_allocation handle gc barriers Reviewed-by: kvn, roland
src/hotspot/share/gc/shared/c2/barrierSetC2.hpp
src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp
src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp
src/hotspot/share/opto/macro.cpp
--- a/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp	Mon Jul 01 12:50:34 2019 +0800
+++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp	Mon Jul 01 10:49:58 2019 +0200
@@ -267,6 +267,7 @@
   virtual bool has_load_barriers() const { return false; }
   virtual bool is_gc_barrier_node(Node* node) const { return false; }
   virtual Node* step_over_gc_barrier(Node* c) const { return c; }
+  virtual Node* step_over_gc_barrier_ctrl(Node* c) const { return c; }
 
   // Support for macro expanded GC barriers
   virtual void register_potential_barrier_node(Node* node) const { }
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp	Mon Jul 01 12:50:34 2019 +0800
+++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp	Mon Jul 01 10:49:58 2019 +0200
@@ -522,7 +522,7 @@
   Node* in_val = barrier->in(LoadBarrierNode::Oop);
   Node* in_adr = barrier->in(LoadBarrierNode::Address);
 
-  Node* out_ctrl = barrier->proj_out_or_null(LoadBarrierNode::Control);
+  Node* out_ctrl = barrier->proj_out(LoadBarrierNode::Control);
   Node* out_res = barrier->proj_out(LoadBarrierNode::Oop);
 
   assert(barrier->in(LoadBarrierNode::Oop) != NULL, "oop to loadbarrier node cannot be null");
@@ -552,9 +552,8 @@
   result_phi->set_req(1, new_loadp);
   result_phi->set_req(2, barrier->in(LoadBarrierNode::Oop));
 
-  if (out_ctrl != NULL) {
-    igvn.replace_node(out_ctrl, result_region);
-  }
+
+  igvn.replace_node(out_ctrl, result_region);
   igvn.replace_node(out_res, result_phi);
 
   assert(barrier->outcnt() == 0,"LoadBarrier macro node has non-null outputs after expansion!");
@@ -640,6 +639,22 @@
   return c;
 }
 
+Node* ZBarrierSetC2::step_over_gc_barrier_ctrl(Node* c) const {
+  Node* node = c;
+
+  // 1. This step follows potential ctrl 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::Control);
+  }
+
+  return c;
+}
+
 bool ZBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const {
   return type == T_OBJECT || type == T_ARRAY;
 }
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp	Mon Jul 01 12:50:34 2019 +0800
+++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp	Mon Jul 01 10:49:58 2019 +0200
@@ -182,6 +182,7 @@
   virtual bool has_load_barriers() const { return true; }
   virtual bool is_gc_barrier_node(Node* node) const;
   virtual Node* step_over_gc_barrier(Node* c) const;
+  virtual Node* step_over_gc_barrier_ctrl(Node* c) const;
 
   virtual void register_potential_barrier_node(Node* node) const;
   virtual void unregister_potential_barrier_node(Node* node) const;
--- a/src/hotspot/share/opto/macro.cpp	Mon Jul 01 12:50:34 2019 +0800
+++ b/src/hotspot/share/opto/macro.cpp	Mon Jul 01 10:49:58 2019 +0200
@@ -1008,8 +1008,17 @@
         assert(init->outcnt() <= 2, "only a control and memory projection expected");
         Node *ctrl_proj = init->proj_out_or_null(TypeFunc::Control);
         if (ctrl_proj != NULL) {
-           assert(init->in(TypeFunc::Control) == _fallthroughcatchproj, "allocation control projection");
-          _igvn.replace_node(ctrl_proj, _fallthroughcatchproj);
+          _igvn.replace_node(ctrl_proj, init->in(TypeFunc::Control));
+#ifdef ASSERT
+          BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
+          Node* tmp = init->in(TypeFunc::Control);
+          while (bs->is_gc_barrier_node(tmp)) {
+            Node* tmp2 = bs->step_over_gc_barrier_ctrl(tmp);
+            assert(tmp != tmp2, "Must make progress");
+            tmp = tmp2;
+          }
+          assert(tmp == _fallthroughcatchproj, "allocation control projection");
+#endif
         }
         Node *mem_proj = init->proj_out_or_null(TypeFunc::Memory);
         if (mem_proj != NULL) {