changeset 9443:f4cde0bdf81b

More efficient barrier elimination.
author rkennke
date Tue, 11 Aug 2015 13:00:15 +0200
parents 02d3bc62ae6b
children 4a1d26f20b62
files src/share/vm/opto/shenandoahSupport.cpp src/share/vm/opto/shenandoahSupport.hpp
diffstat 2 files changed, 91 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/opto/shenandoahSupport.cpp	Tue Aug 11 12:57:55 2015 +0200
+++ b/src/share/vm/opto/shenandoahSupport.cpp	Tue Aug 11 13:00:15 2015 +0200
@@ -1,5 +1,6 @@
 
 #include "opto/callnode.hpp"
+#include "opto/movenode.hpp"
 #include "opto/phaseX.hpp"
 #include "opto/shenandoahSupport.hpp"
 
@@ -43,6 +44,88 @@
   return n;
 }
 
+bool ShenandoahBarrierNode::phi_needs_barrier(PhaseTransform* phase, Node* phi, GrowableArray<Node*>* phistack, Node* rb_mem) {
+  assert(phi->is_Phi(), "expect phi");
+  if (phistack->contains(phi)) {
+    // If we came back to the same phi, then it's a loop in which we don't need a barrier.
+    // Unless we need on another path.
+    return false;
+  }
+  bool need_barrier = false;
+  phistack->push(phi);
+  for (uint i = 1; i < phi->req() && ! need_barrier; i++) {
+    Node* input = phi->in(i);
+    if (input == NULL) {
+      need_barrier = true; // Phi not complete yet?
+    } else if (needs_barrier(phase, input, phistack, rb_mem)) {
+      need_barrier = true;
+    }
+  }
+  phistack->pop();
+  return need_barrier;
+}
+
+bool ShenandoahBarrierNode::needs_barrier(PhaseTransform* phase, Node* n, GrowableArray<Node*>* phistack, Node* rb_mem) {
+  if (n->is_Allocate()) {
+    // tty->print_cr("killed barrier for newly allocated object");
+    return false;;
+  }
+
+  if (n->is_CallJava()) {
+    return true;
+  }
+
+  const Type* type = phase->type(n);
+  if (type->higher_equal(TypePtr::NULL_PTR)) {
+    // tty->print_cr("killed barrier for NULL object");
+    return false;
+  }
+  if (type->isa_oopptr() && type->is_oopptr()->const_oop() != NULL) {
+    // tty->print_cr("killed barrier for constant object");
+    return false;
+  }
+
+  if (n->is_CheckCastPP() || n->is_ConstraintCast()) {
+    return needs_barrier(phase, n->in(1), phistack, rb_mem);
+  }
+  if (n->is_Parm()) {
+    return true;
+  }
+  if (n->is_Proj()) {
+    return needs_barrier(phase, n->in(0), phistack, rb_mem);
+  }
+  if (n->is_Phi()) {
+    return phi_needs_barrier(phase, n, phistack, rb_mem);
+  }
+  if (n->is_CMove()) {
+    return needs_barrier(phase, n->in(CMoveNode::IfFalse), phistack, rb_mem) ||
+      needs_barrier(phase, n->in(CMoveNode::IfTrue ), phistack, rb_mem);
+  }
+  if (n->Opcode() == Op_CreateEx) {
+    return true;
+  }
+  if (n->Opcode() == Op_ShenandoahWriteBarrier) {
+    // tty->print_cr("skipped barrier for chained write barrier object");
+    return false;
+  }
+  if (n->Opcode() == Op_ShenandoahReadBarrier) {
+    if (rb_mem == n->in(Memory)) {
+      // tty->print_cr("Eliminated chained read barrier");
+      return false;
+    } else {
+      return true;
+    }
+  }
+
+  if (n->Opcode() == Op_LoadP) {
+    return true;
+  }
+#ifdef ASSERT
+  tty->print("need barrier on?: "); n->dump();
+#endif
+  return true;
+}
+
 Node* ShenandoahBarrierNode::Identity(PhaseTransform* phase) {
 
 #ifdef ASSERT
@@ -52,21 +135,10 @@
   // if (true) return this;
 
   Node* n = in(ValueIn);
-  if (phase->type(n)->higher_equal(TypePtr::NULL_PTR)) {
-    // tty->print_cr("killed barrier for NULL object");
-    return kill_mem_proj(phase, n);
-  }
-  if (AllocateNode::Ideal_allocation(n, phase) != NULL) {
-    // tty->print_cr("killed barrier for newly allocated object");
-    return kill_mem_proj(phase, n);
-  }
-  if (phase->type(n)->is_oopptr()->const_oop() != NULL) {
-    // tty->print_cr("killed barrier for constant object");
-    return kill_mem_proj(phase, n);
-  }
-
-  if (n->Opcode() == Op_ShenandoahWriteBarrier) {
-    // tty->print_cr("skipped barrier for chained write barrier object");
+  Arena* a = phase->arena();
+  GrowableArray<Node*>* phistack = new (a) GrowableArray<Node*>(a, 4, 0, NULL);
+  Node* rb_mem = Opcode() == Op_ShenandoahReadBarrier ? in(Memory) : NULL;
+  if (! needs_barrier(phase, n, phistack, rb_mem)) {
     return kill_mem_proj(phase, n);
   }
 
--- a/src/share/vm/opto/shenandoahSupport.hpp	Tue Aug 11 12:57:55 2015 +0200
+++ b/src/share/vm/opto/shenandoahSupport.hpp	Tue Aug 11 13:00:15 2015 +0200
@@ -56,6 +56,10 @@
   void check_invariants();
   uint num_mem_projs();
 #endif
+
+private:
+  bool phi_needs_barrier(PhaseTransform* phase, Node* phi, GrowableArray<Node*>* phistack, Node* rb_mem);
+  bool needs_barrier(PhaseTransform* phase, Node* n, GrowableArray<Node*>* phistack, Node* rb_mem);
 };
 
 class ShenandoahReadBarrierNode : public ShenandoahBarrierNode {