Mercurial > hg > jdk9-shenandoah > hotspot
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);