Mercurial > hg > jdk9-shenandoah > hotspot
changeset 9447:3882524b04a9
Reduce memory dependencies of barriers for provingly independent barrier types, or when not needed, e.g. for read barriers on store-values.
author | rkennke |
---|---|
date | Tue, 18 Aug 2015 18:36:41 +0200 |
parents | 553da5b66da3 |
children | e45726f53c00 |
files | src/share/vm/opto/graphKit.cpp src/share/vm/opto/graphKit.hpp src/share/vm/opto/library_call.cpp src/share/vm/opto/parse2.cpp src/share/vm/opto/parse3.cpp src/share/vm/opto/shenandoahSupport.cpp src/share/vm/opto/shenandoahSupport.hpp |
diffstat | 7 files changed, 136 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/vm/opto/graphKit.cpp Tue Aug 18 18:34:37 2015 +0200 +++ b/src/share/vm/opto/graphKit.cpp Tue Aug 18 18:36:41 2015 +0200 @@ -4389,7 +4389,7 @@ // TODO: See comment in load_String_offset(). // TODO: Use incoming ctrl. str = shenandoah_write_barrier(str); - value = shenandoah_read_barrier(value); + value = shenandoah_read_barrier_nomem(value); store_oop_to_object(UseShenandoahGC ? control() : ctrl, str, basic_plus_adr(str, value_offset), value_field_type, value, TypeAryPtr::CHARS, T_OBJECT, MemNode::unordered); @@ -4416,7 +4416,15 @@ return _gvn.transform(new CastPPNode(ary, ary_type->cast_to_stable(true))); } -Node* GraphKit::shenandoah_read_barrier(Node* obj, bool use_ctrl) { +Node* GraphKit::shenandoah_read_barrier(Node* obj) { + return shenandoah_read_barrier_impl(obj, false, true); +} + +Node* GraphKit::shenandoah_read_barrier_nomem(Node* obj) { + return shenandoah_read_barrier_impl(obj, false, false); +} + +Node* GraphKit::shenandoah_read_barrier_impl(Node* obj, bool use_ctrl, bool use_mem) { if (UseShenandoahGC && ShenandoahReadBarrier) { const Type* obj_type = obj->bottom_type(); @@ -4454,8 +4462,10 @@ } else { // We know it is not null. Simple barrier is sufficient. Node* ctrl = use_ctrl ? control() : NULL; - ShenandoahReadBarrierNode* rb = new ShenandoahReadBarrierNode(ctrl, memory(adr_type), obj); + Node* mem = use_mem ? memory(adr_type) : immutable_memory(); + ShenandoahReadBarrierNode* rb = new ShenandoahReadBarrierNode(ctrl, mem, obj); Node* n = _gvn.transform(rb); + record_for_igvn(n); return n; } @@ -4507,11 +4517,10 @@ } else { // We know it is not null. Simple barrier is sufficient. ShenandoahWriteBarrierNode* wb = new ShenandoahWriteBarrierNode(NULL, memory(adr_type), obj); + Node* proj = _gvn.transform(new ShenandoahWBMemProjNode(wb)); + set_memory(proj, adr_type); Node* n = _gvn.transform(wb); - if (n == wb) { // New barrier needs memory projection. - Node* proj = _gvn.transform(new ShenandoahWBMemProjNode(n)); - set_memory(proj, adr_type); - } + record_for_igvn(n); return n; } @@ -4571,8 +4580,8 @@ // Unequal path: retry after read barriers. set_control(iffalse); - a = shenandoah_read_barrier(a, true); - b = shenandoah_read_barrier(b, true); + a = shenandoah_read_barrier_impl(a, true, true); + b = shenandoah_read_barrier_impl(b, true, true); region->init_req(_not_equal, control()); phiA->init_req(_not_equal, a);
--- a/src/share/vm/opto/graphKit.hpp Tue Aug 18 18:34:37 2015 +0200 +++ b/src/share/vm/opto/graphKit.hpp Tue Aug 18 18:36:41 2015 +0200 @@ -895,9 +895,12 @@ // Produce new array node of stable type Node* cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type); - Node* shenandoah_read_barrier(Node* obj, bool use_ctrl = false); + Node* shenandoah_read_barrier(Node* obj); + Node* shenandoah_read_barrier_nomem(Node* obj); Node* shenandoah_write_barrier(Node* obj); void shenandoah_acmp_barrier(Node*& a, Node*& b); +private: + Node* shenandoah_read_barrier_impl(Node* obj, bool use_ctrl, bool use_mem); }; // Helper class to support building of control flow branches. Upon
--- a/src/share/vm/opto/library_call.cpp Tue Aug 18 18:34:37 2015 +0200 +++ b/src/share/vm/opto/library_call.cpp Tue Aug 18 18:36:41 2015 +0200 @@ -2778,7 +2778,7 @@ if (type != T_OBJECT ) { (void) store_to_memory(control(), adr, val, type, adr_type, mo, is_volatile); } else { - val = shenandoah_read_barrier(val); + val = shenandoah_read_barrier_nomem(val); // Possibly an oop being stored to Java heap or native memory if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) { // oop to Java heap. @@ -2981,7 +2981,7 @@ if (_gvn.type(newval) == TypePtr::NULL_PTR) newval = _gvn.makecon(TypePtr::NULL_PTR); - newval = shenandoah_read_barrier(newval); + newval = shenandoah_read_barrier_nomem(newval); // Reference stores need a store barrier. if (kind == LS_xchg) { @@ -3184,7 +3184,7 @@ const bool require_atomic_access = true; Node* store; if (type == T_OBJECT) { // reference stores need a store barrier. - val = shenandoah_read_barrier(val); + val = shenandoah_read_barrier_nomem(val); store = store_oop_to_unknown(control(), base, adr, adr_type, val, type, MemNode::release); } else {
--- a/src/share/vm/opto/parse2.cpp Tue Aug 18 18:34:37 2015 +0200 +++ b/src/share/vm/opto/parse2.cpp Tue Aug 18 18:36:41 2015 +0200 @@ -1732,7 +1732,7 @@ // a is not used except for an assert. The address d already has the // write barrier. Adding a barrier on a only results in additional code // being generated. - c = shenandoah_read_barrier(c); + c = shenandoah_read_barrier_nomem(c); Node* store = store_oop_to_array(control(), a, d, adr_type, c, elemtype, T_OBJECT, StoreNode::release_if_reference(T_OBJECT)); break;
--- a/src/share/vm/opto/parse3.cpp Tue Aug 18 18:34:37 2015 +0200 +++ b/src/share/vm/opto/parse3.cpp Tue Aug 18 18:36:41 2015 +0200 @@ -322,7 +322,7 @@ field_type = TypeOopPtr::make_from_klass(field->type()->as_klass()); } - val = shenandoah_read_barrier(val); + val = shenandoah_read_barrier_nomem(val); store = store_oop_to_object(control(), obj, adr, adr_type, val, field_type, bt, mo); } else {
--- a/src/share/vm/opto/shenandoahSupport.cpp Tue Aug 18 18:34:37 2015 +0200 +++ b/src/share/vm/opto/shenandoahSupport.cpp Tue Aug 18 18:36:41 2015 +0200 @@ -126,6 +126,108 @@ return true; } +bool ShenandoahReadBarrierNode::is_independent(const Type* in_type, const Type* this_type) const { + assert(in_type->isa_oopptr(), "expect oop ptr"); + assert(this_type->isa_oopptr(), "expect oop ptr"); + /* + if ((! in_type->isa_oopptr()) || (! this_type->isa_oopptr())) { +#ifdef ASSERT + tty->print_cr("not oopptr"); + tty->print("in: "); in_type->dump(); tty->print_cr(" "); + tty->print("this: "); this_type->dump(); tty->print_cr(" "); +#endif + return false; + } + */ + + ciKlass* in_kls = in_type->is_oopptr()->klass(); + ciKlass* this_kls = this_type->is_oopptr()->klass(); + if ((!in_kls->is_subclass_of(this_kls)) && + (!this_kls->is_subclass_of(in_kls))) { +#ifdef ASSERT + // tty->print_cr("independent: "); + // tty->print("in: "); in_kls->print(); tty->print_cr(" "); + // tty->print("this: "); this_kls->print(); tty->print_cr(" "); +#endif + return true; + } +#ifdef ASSERT + // tty->print_cr("possibly dependend?"); + // tty->print("in: "); in_type->dump(); tty->print_cr(" "); + // tty->print("this: "); this_type->dump(); tty->print_cr(" "); +#endif + return false; +} + +Node* ShenandoahReadBarrierNode::Ideal(PhaseGVN *phase, bool can_reshape) { + + if (! can_reshape) { + return NULL; + } + + Node* input = in(Memory); + if (input->Opcode() == Op_ShenandoahWBMemProj) { + input = input->in(0); + assert(input->Opcode() == Op_ShenandoahWriteBarrier, "expect write barrier"); + const Type* in_type = input->bottom_type(); // phase->type(input); + const Type* this_type = bottom_type(); //phase->type(this); + if (is_independent(in_type, this_type)) { + set_req(Memory, input->in(Memory)); + return this; + } + } + return NULL; +} + +uint ShenandoahWriteBarrierNode::count_rb_users(Node* n, GrowableArray<Node*>* phistack) const { + uint count = 0; + for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { + Node* o = n->fast_out(j); + if (o->Opcode() == Op_ShenandoahReadBarrier || + o->Opcode() == Op_ShenandoahWriteBarrier) { + // tty->print("counting barrier"); o->dump(); + count++; + } else if (o->isa_Phi()) { + if (! phistack->contains(o)) { + phistack->push(o); + count += count_rb_users(o, phistack); + phistack->pop(); + } + } else { + // tty->print("not counting: "); o->dump(); + } + } + return count; +} + +Node* ShenandoahWriteBarrierNode::Ideal(PhaseGVN *phase, bool can_reshape) { + + if (! can_reshape) return NULL; + + if (in(Memory) == phase->C->immutable_memory()) return NULL; + + Node* mem_proj = find_out_with(Op_ShenandoahWBMemProj); + if (mem_proj == NULL) { + // tty->print_cr("no mem proj: kill input mem"); + set_req(Memory, phase->C->immutable_memory()); + return this; + } + + Arena* a = phase->arena(); + GrowableArray<Node*>* phistack = new (a) GrowableArray<Node*>(a, 4, 0, NULL); + uint num_users = count_rb_users(mem_proj, phistack); + if (num_users == 0) { + // tty->print_cr("no users of mem projection. kill input mem"); + set_req(Memory, phase->C->immutable_memory()); + + // tty->print_cr("reshaped wb: "); + // dump(); + return this; + } + // tty->print_cr("leave mem proj alone"); + return NULL; +} + Node* ShenandoahBarrierNode::Identity(PhaseTransform* phase) { #ifdef ASSERT
--- a/src/share/vm/opto/shenandoahSupport.hpp Tue Aug 18 18:34:37 2015 +0200 +++ b/src/share/vm/opto/shenandoahSupport.hpp Tue Aug 18 18:36:41 2015 +0200 @@ -68,8 +68,12 @@ : ShenandoahBarrierNode(ctrl, mem, obj) { } + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual Node* Identity(PhaseTransform* phase); virtual int Opcode() const; +private: + bool is_independent(const Type* in_type, const Type* this_type) const; + }; class ShenandoahWriteBarrierNode : public ShenandoahBarrierNode { @@ -80,11 +84,14 @@ } virtual int Opcode() const; + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); // virtual void set_req( uint i, Node *n ) { // if (i == MemNode::Memory) { assert(n == Compiler::current()->immutable_memory(), "set only immutable mem on wb"); } // Node::set_req(i, n); // } +private: + uint count_rb_users(Node* n, GrowableArray<Node*>* phistack) const; }; class ShenandoahWBMemProjNode : public ProjNode {