changeset 9442:02d3bc62ae6b

Implement more efficient barrier for acmp.
author rkennke
date Tue, 11 Aug 2015 12:57:55 +0200
parents 0f1a8f65ef66
children f4cde0bdf81b
files src/share/vm/opto/graphKit.cpp src/share/vm/opto/graphKit.hpp src/share/vm/opto/parse2.cpp
diffstat 3 files changed, 74 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/opto/graphKit.cpp	Thu Jul 30 15:51:45 2015 +0200
+++ b/src/share/vm/opto/graphKit.cpp	Tue Aug 11 12:57:55 2015 +0200
@@ -4416,7 +4416,7 @@
   return _gvn.transform(new CastPPNode(ary, ary_type->cast_to_stable(true)));
 }
 
-Node* GraphKit::shenandoah_read_barrier(Node* obj) {
+Node* GraphKit::shenandoah_read_barrier(Node* obj, bool use_ctrl) {
 
   if (UseShenandoahGC && ShenandoahReadBarrier) {
     const Type* obj_type = obj->bottom_type();
@@ -4440,7 +4440,8 @@
       region->init_req(_null_path, null_ctrl);
       phi   ->init_req(_null_path, obj);
 
-      ShenandoahReadBarrierNode* rb = new ShenandoahReadBarrierNode(NULL, memory(adr_type), not_null_obj);
+      Node* ctrl = use_ctrl ? control() : NULL;
+      ShenandoahReadBarrierNode* rb = new ShenandoahReadBarrierNode(ctrl, memory(adr_type), not_null_obj);
       Node* n = _gvn.transform(rb);
 
       region->init_req(_not_null_path, control());
@@ -4452,7 +4453,8 @@
 
     } else {
       // We know it is not null. Simple barrier is sufficient.
-      ShenandoahReadBarrierNode* rb = new ShenandoahReadBarrierNode(NULL, memory(adr_type), obj);
+      Node* ctrl = use_ctrl ? control() : NULL;
+      ShenandoahReadBarrierNode* rb = new ShenandoahReadBarrierNode(ctrl, memory(adr_type), obj);
       Node* n = _gvn.transform(rb);
       return n;
     }
@@ -4519,3 +4521,69 @@
     return obj;
   }
 }
+
+void GraphKit::shenandoah_acmp_barrier(Node*& a, Node*& b) {
+  if (UseShenandoahGC) {
+    const Type* a_type = a->bottom_type();
+    const Type* b_type = b->bottom_type();
+    if (a_type->higher_equal(TypePtr::NULL_PTR) || b_type->higher_equal(TypePtr::NULL_PTR)) {
+      // We know one arg is gonna be null. No need for barriers.
+      // tty->print_cr("eliminate acmp barrier on null");
+      return;
+    }
+    /*
+    if ((!a_type->isa_oopptr()) || (!b_type->isa_oopptr())) {
+      a_type->dump();
+      b_type->dump();
+    }
+    */
+    if (a_type->is_oopptr()->const_oop() != NULL && b_type->is_oopptr()->const_oop() != NULL ) {
+      // We know one arg is inlined constant. No need for barriers.
+      // tty->print_cr("eliminate acmp barrier on constant");
+      return;
+    }
+    if (a->Opcode() == Op_ShenandoahWriteBarrier && b->Opcode() == Op_ShenandoahWriteBarrier) {
+      // We know one arg is already write-barrier'd. No need for barriers.
+      // tty->print_cr("eliminate acmp barrier on write barrier");
+      return;
+    }
+    if (AllocateNode::Ideal_allocation(a, &_gvn) != NULL || AllocateNode::Ideal_allocation(b, &_gvn) != NULL) {
+      // We know one arg is already in to-space. No need for barriers.
+      // tty->print_cr("eliminate acmp barrier on new obj");
+      return;
+    }
+
+    enum { _equal = 1, _not_equal, PATH_LIMIT };
+    RegionNode* region = new RegionNode(PATH_LIMIT);
+    PhiNode* phiA = PhiNode::make(region, a);
+    PhiNode* phiB = PhiNode::make(region, b);
+
+    Node* cmp = _gvn.transform(new CmpPNode(b, a));
+    Node* tst = _gvn.transform(new BoolNode(cmp, BoolTest::eq));
+
+    // TODO: Use profiling data.
+    IfNode* iff = create_and_map_if(control(), tst, PROB_FAIR, COUNT_UNKNOWN);
+    Node* iftrue = _gvn.transform(new IfTrueNode(iff));
+    Node* iffalse = _gvn.transform(new IfFalseNode(iff));
+
+    // Equal path: Use original values.
+    region->init_req(_equal, iftrue);
+    phiA->init_req(_equal, a);
+    phiB->init_req(_equal, b);
+
+    // Unequal path: retry after read barriers.
+    set_control(iffalse);
+    a = shenandoah_read_barrier(a, true);
+    b = shenandoah_read_barrier(b, true);
+
+    region->init_req(_not_equal, control());
+    phiA->init_req(_not_equal, a);
+    phiB->init_req(_not_equal, b);
+
+    set_control(_gvn.transform(region));
+    record_for_igvn(region);
+
+    a = _gvn.transform(phiA);
+    b = _gvn.transform(phiB);
+  }
+}
--- a/src/share/vm/opto/graphKit.hpp	Thu Jul 30 15:51:45 2015 +0200
+++ b/src/share/vm/opto/graphKit.hpp	Tue Aug 11 12:57:55 2015 +0200
@@ -895,9 +895,9 @@
   // Produce new array node of stable type
   Node* cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type);
 
-  Node* shenandoah_read_barrier(Node* obj);
+  Node* shenandoah_read_barrier(Node* obj, bool use_ctrl = false);
   Node* shenandoah_write_barrier(Node* obj);
-
+  void shenandoah_acmp_barrier(Node*& a, Node*& b);
 };
 
 // Helper class to support building of control flow branches. Upon
--- a/src/share/vm/opto/parse2.cpp	Thu Jul 30 15:51:45 2015 +0200
+++ b/src/share/vm/opto/parse2.cpp	Tue Aug 11 12:57:55 2015 +0200
@@ -2286,8 +2286,7 @@
     maybe_add_safepoint(iter().get_dest());
     a = pop();
     b = pop();
-    a = shenandoah_write_barrier(a);
-    b = shenandoah_write_barrier(b);
+    shenandoah_acmp_barrier(a, b);
     c = _gvn.transform( new CmpPNode(b, a) );
     c = optimize_cmp_with_klass(c);
     do_if(btest, c);