--- old/src/hotspot/share/ci/ciInstanceKlass.cpp 2018-10-16 17:48:33.423198978 +0200 +++ new/src/hotspot/share/ci/ciInstanceKlass.cpp 2018-10-16 17:48:25.020218294 +0200 @@ -65,6 +65,7 @@ _is_unsafe_anonymous = ik->is_unsafe_anonymous(); _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: _has_injected_fields = -1; + _has_object_fields = -1; _implementor = NULL; // we will fill these lazily // Ensure that the metadata wrapped by the ciMetadata is kept alive by GC. @@ -122,6 +123,7 @@ _has_nonstatic_fields = false; _nonstatic_fields = NULL; _has_injected_fields = -1; + _has_object_fields = -1; _is_unsafe_anonymous = false; _loader = loader; _protection_domain = protection_domain; @@ -554,6 +556,19 @@ _has_injected_fields = has_injected_fields; } +void ciInstanceKlass::compute_object_fields() { + for (int i = 0; i < nof_nonstatic_fields(); i++) { + ciField* f = nonstatic_field_at(i); + if (f->layout_type() == T_OBJECT) { + assert(_has_object_fields == -1 || _has_object_fields == 1, "broken concurrent initialization"); + _has_object_fields = 1; + return; + } + } + assert(_has_object_fields == -1 || _has_object_fields == 0, "broken concurrent initialization"); + _has_object_fields = 0; +} + // ------------------------------------------------------------------ // ciInstanceKlass::find_method // --- old/src/hotspot/share/ci/ciInstanceKlass.hpp 2018-10-16 17:48:41.813179691 +0200 +++ new/src/hotspot/share/ci/ciInstanceKlass.hpp 2018-10-16 17:48:33.524198745 +0200 @@ -66,6 +66,7 @@ ciConstantPoolCache* _field_cache; // cached map index->field GrowableArray* _nonstatic_fields; int _has_injected_fields; // any non static injected fields? lazily initialized. + int _has_object_fields; // any object fields? lazily initialized. // The possible values of the _implementor fall into following three cases: // NULL: no implementor. @@ -75,6 +76,7 @@ void compute_injected_fields(); bool compute_injected_fields_helper(); + void compute_object_fields(); protected: ciInstanceKlass(Klass* k); @@ -202,6 +204,13 @@ return _has_injected_fields > 0 ? true : false; } + bool has_object_fields() { + if (_has_object_fields == -1) { + compute_object_fields(); + } + return _has_object_fields > 0 ? true : false; + } + // nth nonstatic field (presented by ascending address) ciField* nonstatic_field_at(int i) { assert(_nonstatic_fields != NULL, ""); --- old/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp 2018-10-16 17:48:50.268160255 +0200 +++ new/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp 2018-10-16 17:48:41.906179477 +0200 @@ -203,6 +203,8 @@ Expansion }; virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const { return false; } + virtual Node* array_copy_load_store_barrier(PhaseGVN *phase, bool can_reshape, Node* v, MergeMemNode* mem, Node*& ctl) const { return v; } + virtual void array_copy_post_barrier_at_expansion(ArrayCopyNode* ac, Node*& c, Node*& m, PhaseIterGVN& igvn) const { } // Support for GC barriers emitted during parsing virtual bool has_load_barriers() const { return false; } @@ -213,8 +215,8 @@ virtual void register_potential_barrier_node(Node* node) const { } virtual void unregister_potential_barrier_node(Node* node) const { } virtual void eliminate_gc_barrier(PhaseMacroExpand* macro, Node* node) const { } - virtual void enqueue_useful_gc_barrier(Unique_Node_List &worklist, Node* node) const {} - virtual void eliminate_useless_gc_barriers(Unique_Node_List &useful) const {} + virtual void enqueue_useful_gc_barrier(PhaseIterGVN* igvn, Node* node) const {} + virtual void eliminate_useless_gc_barriers(Unique_Node_List &useful, Compile* C) const {} virtual void add_users_to_worklist(Unique_Node_List* worklist) const {} // Allow barrier sets to have shared state that is preserved across a compilation unit. --- old/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp 2018-10-16 17:48:58.894140425 +0200 +++ new/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp 2018-10-16 17:48:50.363160036 +0200 @@ -102,7 +102,7 @@ } } -void ZBarrierSetC2::eliminate_useless_gc_barriers(Unique_Node_List &useful) const { +void ZBarrierSetC2::eliminate_useless_gc_barriers(Unique_Node_List &useful, Compile* C) const { // Remove useless LoadBarrier nodes ZBarrierSetC2State* s = state(); for (int i = s->load_barrier_count()-1; i >= 0; i--) { @@ -113,9 +113,9 @@ } } -void ZBarrierSetC2::enqueue_useful_gc_barrier(Unique_Node_List &worklist, Node* node) const { +void ZBarrierSetC2::enqueue_useful_gc_barrier(PhaseIterGVN* igvn, Node* node) const { if (node->is_LoadBarrier() && !node->as_LoadBarrier()->has_true_uses()) { - worklist.push(node); + igvn->_worklist.push(node); } } --- old/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp 2018-10-16 17:49:07.353120979 +0200 +++ new/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp 2018-10-16 17:48:58.998140186 +0200 @@ -189,9 +189,9 @@ virtual bool has_load_barriers() const { return true; } virtual bool is_gc_barrier_node(Node* node) const; virtual void eliminate_gc_barrier(PhaseMacroExpand* macro, Node* node) const { } - virtual void eliminate_useless_gc_barriers(Unique_Node_List &useful) const; + virtual void eliminate_useless_gc_barriers(Unique_Node_List &useful, Compile* C) const; virtual void add_users_to_worklist(Unique_Node_List* worklist) const; - virtual void enqueue_useful_gc_barrier(Unique_Node_List &worklist, Node* node) const; + virtual void enqueue_useful_gc_barrier(PhaseIterGVN* igvn, Node* node) const; virtual void register_potential_barrier_node(Node* node) const; virtual void unregister_potential_barrier_node(Node* node) const; virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const; --- old/src/hotspot/share/opto/arraycopynode.cpp 2018-10-16 17:49:15.807101546 +0200 +++ new/src/hotspot/share/opto/arraycopynode.cpp 2018-10-16 17:49:07.446120766 +0200 @@ -182,6 +182,7 @@ ciInstanceKlass* ik = inst_src->klass()->as_instance_klass(); assert(ik->nof_nonstatic_fields() <= ArrayCopyLoadStoreMaxElem, "too many fields"); + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); for (int i = 0; i < count; i++) { ciField* field = ik->nonstatic_field_at(i); int fieldidx = phase->C->alias_type(field)->index(); @@ -205,6 +206,9 @@ Node* v = LoadNode::make(*phase, ctl, mem->memory_at(fieldidx), next_src, adr_type, type, bt, MemNode::unordered); v = phase->transform(v); + if (bt == T_OBJECT) { + v = bs->array_copy_load_store_barrier(phase, can_reshape, v, mem, ctl); + } Node* s = StoreNode::make(*phase, ctl, mem->memory_at(fieldidx), next_dest, adr_type, v, bt, MemNode::unordered); s = phase->transform(s); mem->set_memory_at(fieldidx, s); @@ -376,8 +380,12 @@ bool same_alias = (alias_idx_src == alias_idx_dest); if (count > 0) { + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); Node* v = LoadNode::make(*phase, forward_ctl, start_mem_src, adr_src, atp_src, value_type, copy_type, MemNode::unordered); v = phase->transform(v); + if (copy_type == T_OBJECT) { + v = bs->array_copy_load_store_barrier(phase, can_reshape, v, mm, forward_ctl); + } mem = StoreNode::make(*phase, forward_ctl, mem, adr_dest, atp_dest, v, copy_type, MemNode::unordered); mem = phase->transform(mem); for (int i = 1; i < count; i++) { @@ -386,6 +394,9 @@ Node* next_dest = phase->transform(new AddPNode(base_dest,adr_dest,off)); v = LoadNode::make(*phase, forward_ctl, same_alias ? mem : start_mem_src, next_src, atp_src, value_type, copy_type, MemNode::unordered); v = phase->transform(v); + if (copy_type == T_OBJECT) { + v = bs->array_copy_load_store_barrier(phase, can_reshape, v, mm, forward_ctl); + } mem = StoreNode::make(*phase, forward_ctl,mem,next_dest,atp_dest,v, copy_type, MemNode::unordered); mem = phase->transform(mem); } @@ -433,11 +444,17 @@ Node* next_dest = phase->transform(new AddPNode(base_dest,adr_dest,off)); Node* v = LoadNode::make(*phase, backward_ctl, same_alias ? mem : start_mem_src, next_src, atp_src, value_type, copy_type, MemNode::unordered); v = phase->transform(v); + if (copy_type == T_OBJECT) { + v = bs->array_copy_load_store_barrier(phase, can_reshape, v, mm, backward_ctl); + } mem = StoreNode::make(*phase, backward_ctl,mem,next_dest,atp_dest,v, copy_type, MemNode::unordered); mem = phase->transform(mem); } Node* v = LoadNode::make(*phase, backward_ctl, same_alias ? mem : start_mem_src, adr_src, atp_src, value_type, copy_type, MemNode::unordered); v = phase->transform(v); + if (copy_type == T_OBJECT) { + v = bs->array_copy_load_store_barrier(phase, can_reshape, v, mm, backward_ctl); + } mem = StoreNode::make(*phase, backward_ctl, mem, adr_dest, atp_dest, v, copy_type, MemNode::unordered); mem = phase->transform(mem); mm->set_memory_at(alias_idx_dest, mem); --- old/src/hotspot/share/opto/cfgnode.cpp 2018-10-16 17:49:24.315081987 +0200 +++ new/src/hotspot/share/opto/cfgnode.cpp 2018-10-16 17:49:15.906101318 +0200 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/systemDictionary.hpp" +#include "gc/shared/c2/barrierSetC2.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" #include "oops/objArrayKlass.hpp" @@ -1447,7 +1448,10 @@ } else return NULL; // Build int->bool conversion - Node *n = new Conv2BNode( cmp->in(1) ); + Node *in1 = cmp->in(1); + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); + in1 = bs->step_over_gc_barrier(in1); + Node *n = new Conv2BNode(in1); if( flipped ) n = new XorINode( phase->transform(n), phase->intcon(1) ); @@ -1813,7 +1817,12 @@ if (can_reshape && igvn != NULL) { igvn->_worklist.push(r); } - set_req(j, top); // Nuke it down + // Nuke it down + if (can_reshape) { + set_req_X(j, top, igvn); + } else { + set_req(j, top); + } progress = this; // Record progress } } --- old/src/hotspot/share/opto/compile.cpp 2018-10-16 17:49:32.887062282 +0200 +++ new/src/hotspot/share/opto/compile.cpp 2018-10-16 17:49:24.445081688 +0200 @@ -421,7 +421,7 @@ } } BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - bs->eliminate_useless_gc_barriers(useful); + bs->eliminate_useless_gc_barriers(useful, this); // clean up the late inline lists remove_useless_late_inlines(&_string_late_inlines, useful); remove_useless_late_inlines(&_boxing_late_inlines, useful); --- old/src/hotspot/share/opto/graphKit.cpp 2018-10-16 17:49:41.352042823 +0200 +++ new/src/hotspot/share/opto/graphKit.cpp 2018-10-16 17:49:33.008062004 +0200 @@ -3726,6 +3726,10 @@ if (ptr == NULL) { // reduce dumb test in callers return NULL; } + + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); + ptr = bs->step_over_gc_barrier(ptr); + if (ptr->is_CheckCastPP()) { // strip only one raw-to-oop cast ptr = ptr->in(1); if (ptr == NULL) return NULL; --- old/src/hotspot/share/opto/loopPredicate.cpp 2018-10-16 17:49:49.585023897 +0200 +++ new/src/hotspot/share/opto/loopPredicate.cpp 2018-10-16 17:49:41.468042556 +0200 @@ -301,6 +301,62 @@ return clone_loop_predicates(old_entry, new_entry, clone_limit_check, this, &this->_igvn); } +void PhaseIdealLoop::clone_loop_predicates_fix_mem(ProjNode* dom_proj , ProjNode* proj, + PhaseIdealLoop* loop_phase, + PhaseIterGVN* igvn) { + Compile* C = NULL; + if (loop_phase != NULL) { + igvn = &loop_phase->igvn(); + } + C = igvn->C; + ProjNode* other_dom_proj = dom_proj->in(0)->as_Multi()->proj_out(1-dom_proj->_con); + Node* dom_r = other_dom_proj->unique_ctrl_out(); + if (dom_r->is_Region()) { + assert(dom_r->unique_ctrl_out()->is_Call(), "unc expected"); + ProjNode* other_proj = proj->in(0)->as_Multi()->proj_out(1-proj->_con); + Node* r = other_proj->unique_ctrl_out(); + assert(r->is_Region() && r->unique_ctrl_out()->is_Call(), "cloned predicate should have caused region to be added"); + for (DUIterator_Fast imax, i = dom_r->fast_outs(imax); i < imax; i++) { + Node* dom_use = dom_r->fast_out(i); + if (dom_use->is_Phi() && dom_use->bottom_type() == Type::MEMORY) { + assert(dom_use->in(0) == dom_r, ""); + Node* phi = NULL; + for (DUIterator_Fast jmax, j = r->fast_outs(jmax); j < jmax; j++) { + Node* use = r->fast_out(j); + if (use->is_Phi() && use->bottom_type() == Type::MEMORY && + use->adr_type() == dom_use->adr_type()) { + assert(use->in(0) == r, ""); + assert(phi == NULL, "only one phi"); + phi = use; + } + } + if (phi == NULL) { + Node* call = r->unique_ctrl_out(); + Node* mem = call->in(TypeFunc::Memory); + MergeMemNode* mm = NULL; + if (mem->is_MergeMem()) { + mm = mem->clone()->as_MergeMem(); + } else { + mm = MergeMemNode::make(mem); + } + phi = PhiNode::make(r, mem, Type::MEMORY, dom_use->adr_type()); + mm->set_memory_at(C->get_alias_index(phi->adr_type()), phi); + if (loop_phase != NULL) { + loop_phase->register_new_node(mm, r); + loop_phase->register_new_node(phi, r); + } else { + igvn->register_new_node_with_optimizer(mm); + igvn->register_new_node_with_optimizer(phi); + } + igvn->replace_input_of(call, TypeFunc::Memory, mm); + } + igvn->replace_input_of(phi, r->req()-1, dom_use->in(dom_r->find_edge(other_dom_proj))); + } + } + } +} + + // Clone loop predicates to cloned loops (peeled, unswitched, split_if). Node* PhaseIdealLoop::clone_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check, @@ -333,14 +389,24 @@ } if (predicate_proj != NULL) { // right pattern that can be used by loop predication // clone predicate - new_entry = clone_predicate(predicate_proj, new_entry, + ProjNode* proj = clone_predicate(predicate_proj, new_entry, Deoptimization::Reason_predicate, loop_phase, igvn); - assert(new_entry != NULL && new_entry->is_Proj(), "IfTrue or IfFalse after clone predicate"); + assert(proj != NULL, "IfTrue or IfFalse after clone predicate"); + new_entry = proj; if (TraceLoopPredicate) { tty->print("Loop Predicate cloned: "); debug_only( new_entry->in(0)->dump(); ); } + if (profile_predicate_proj != NULL) { + // A node that produces memory may be out of loop and depend on + // a profiled predicates. In that case the memory state at the + // end of profiled predicates and at the end of predicates are + // not the same. The cloned predicates are dominated by the + // profiled predicates but may have the wrong memory + // state. Update it. + clone_loop_predicates_fix_mem(profile_predicate_proj, proj, loop_phase, igvn); + } } if (profile_predicate_proj != NULL) { // right pattern that can be used by loop predication // clone predicate --- old/src/hotspot/share/opto/loopnode.hpp 2018-10-16 17:49:58.105004311 +0200 +++ new/src/hotspot/share/opto/loopnode.hpp 2018-10-16 17:49:49.685023667 +0200 @@ -1081,6 +1081,10 @@ PhaseIdealLoop* loop_phase, PhaseIterGVN* igvn); + static void clone_loop_predicates_fix_mem(ProjNode* dom_proj , ProjNode* proj, + PhaseIdealLoop* loop_phase, + PhaseIterGVN* igvn ); + static Node* clone_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check, PhaseIdealLoop* loop_phase, --- old/src/hotspot/share/opto/macro.cpp 2018-10-16 17:50:06.436985157 +0200 +++ new/src/hotspot/share/opto/macro.cpp 2018-10-16 17:49:58.206004079 +0200 @@ -434,7 +434,10 @@ if (val == mem) { values.at_put(j, mem); } else if (val->is_Store()) { - values.at_put(j, val->in(MemNode::ValueIn)); + Node* n = val->in(MemNode::ValueIn); + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); + n = bs->step_over_gc_barrier(n); + values.at_put(j, n); } else if(val->is_Proj() && val->in(0) == alloc) { values.at_put(j, _igvn.zerocon(ft)); } else if (val->is_Phi()) { @@ -546,7 +549,10 @@ // hit a sentinel, return appropriate 0 value return _igvn.zerocon(ft); } else if (mem->is_Store()) { - return mem->in(MemNode::ValueIn); + Node* n = mem->in(MemNode::ValueIn); + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); + n = bs->step_over_gc_barrier(n); + return n; } else if (mem->is_Phi()) { // attempt to produce a Phi reflecting the values on the input paths of the Phi Node_Stack value_phis(a, 8); @@ -934,6 +940,7 @@ } k -= (oc2 - use->outcnt()); } + _igvn.remove_dead_node(use); } else if (use->is_ArrayCopy()) { // Disconnect ArrayCopy node ArrayCopyNode* ac = use->as_ArrayCopy(); --- old/src/hotspot/share/opto/macro.hpp 2018-10-16 17:50:14.972965535 +0200 +++ new/src/hotspot/share/opto/macro.hpp 2018-10-16 17:50:06.544984909 +0200 @@ -176,6 +176,7 @@ Node* src, Node* src_offset, Node* dest, Node* dest_offset, Node* copy_length, bool dest_uninitialized); + bool clone_needs_postbarrier(ArrayCopyNode *ac); void expand_arraycopy_node(ArrayCopyNode *ac); --- old/src/hotspot/share/opto/macroArrayCopy.cpp 2018-10-16 17:50:23.332946317 +0200 +++ new/src/hotspot/share/opto/macroArrayCopy.cpp 2018-10-16 17:50:15.067965316 +0200 @@ -72,7 +72,6 @@ Node* parm2, Node* parm3, Node* parm4, Node* parm5, Node* parm6, Node* parm7) { - int size = call_type->domain()->cnt(); Node* call = new CallLeafNoFPNode(call_type, call_addr, call_name, adr_type); call->init_req(TypeFunc::Control, ctrl); call->init_req(TypeFunc::I_O , top()); @@ -1083,6 +1082,33 @@ finish_arraycopy_call(call, ctrl, mem, adr_type); } +bool PhaseMacroExpand::clone_needs_postbarrier(ArrayCopyNode *ac) { + Node* src = ac->in(ArrayCopyNode::Src); + const TypeOopPtr* src_type = _igvn.type(src)->is_oopptr(); + if (src_type->isa_instptr() != NULL) { + ciInstanceKlass* ik = src_type->klass()->as_instance_klass(); + if ((src_type->klass_is_exact() || (!ik->is_interface() && !ik->has_subklass())) && !ik->has_injected_fields()) { + if (ik->has_object_fields()) { + return true; + } else { + if (!src_type->klass_is_exact()) { + C->dependencies()->assert_leaf_type(ik); + } + } + } else { + return true; + } + } else if (src_type->isa_aryptr()) { + BasicType src_elem = src_type->klass()->as_array_klass()->element_type()->basic_type(); + if (src_elem == T_OBJECT || src_elem == T_ARRAY) { + return true; + } + } else { + return true; + } + return false; +} + void PhaseMacroExpand::expand_arraycopy_node(ArrayCopyNode *ac) { Node* ctrl = ac->in(TypeFunc::Control); Node* io = ac->in(TypeFunc::I_O); @@ -1107,7 +1133,21 @@ Node* call = make_leaf_call(ctrl, mem, call_type, copyfunc_addr, copyfunc_name, raw_adr_type, src, dest, length XTOP); transform_later(call); + if (clone_needs_postbarrier(ac)) { + const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM; + Node* c = new ProjNode(call,TypeFunc::Control); + transform_later(c); + Node* m = new ProjNode(call, TypeFunc::Memory); + transform_later(m); + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); + bs->array_copy_post_barrier_at_expansion(ac, c, m, _igvn); + Node* out_c = ac->proj_out(TypeFunc::Control); + Node* out_m = ac->proj_out(TypeFunc::Memory); + _igvn.replace_node(out_c, c); + _igvn.replace_node(out_m, m); + } else { _igvn.replace_node(ac, call); + } return; } else if (ac->is_copyof() || ac->is_copyofrange() || ac->is_cloneoop()) { Node* mem = ac->in(TypeFunc::Memory); --- old/src/hotspot/share/opto/memnode.cpp 2018-10-16 17:50:31.829926784 +0200 +++ new/src/hotspot/share/opto/memnode.cpp 2018-10-16 17:50:23.437946075 +0200 @@ -924,8 +924,10 @@ if (ac->as_ArrayCopy()->is_clonebasic()) { assert(ld_alloc != NULL, "need an alloc"); assert(addp->is_AddP(), "address must be addp"); - assert(addp->in(AddPNode::Base) == ac->in(ArrayCopyNode::Dest)->in(AddPNode::Base), "strange pattern"); - assert(addp->in(AddPNode::Address) == ac->in(ArrayCopyNode::Dest)->in(AddPNode::Address), "strange pattern"); + assert(ac->in(ArrayCopyNode::Dest)->is_AddP(), "dest must be an address"); + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); + assert(bs->step_over_gc_barrier(addp->in(AddPNode::Base)) == bs->step_over_gc_barrier(ac->in(ArrayCopyNode::Dest)->in(AddPNode::Base)), "strange pattern"); + assert(bs->step_over_gc_barrier(addp->in(AddPNode::Address)) == bs->step_over_gc_barrier(ac->in(ArrayCopyNode::Dest)->in(AddPNode::Address)), "strange pattern"); addp->set_req(AddPNode::Base, src->in(AddPNode::Base)); addp->set_req(AddPNode::Address, src->in(AddPNode::Address)); } else { @@ -1081,6 +1083,8 @@ (tp != NULL) && tp->is_ptr_to_boxed_value()) { intptr_t ignore = 0; Node* base = AddPNode::Ideal_base_and_offset(ld_adr, phase, ignore); + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); + base = bs->step_over_gc_barrier(base); if (base != NULL && base->is_Proj() && base->as_Proj()->_con == TypeFunc::Parms && base->in(0)->is_CallStaticJava() && --- old/src/hotspot/share/opto/node.cpp 2018-10-16 17:50:40.325907253 +0200 +++ new/src/hotspot/share/opto/node.cpp 2018-10-16 17:50:31.952926501 +0200 @@ -1389,7 +1389,7 @@ // and remove_globally_dead_node(). igvn->add_users_to_worklist( n ); } else { - BarrierSet::barrier_set()->barrier_set_c2()->enqueue_useful_gc_barrier(igvn->_worklist, n); + BarrierSet::barrier_set()->barrier_set_c2()->enqueue_useful_gc_barrier(igvn, n); } } } --- old/src/hotspot/share/opto/phaseX.cpp 2018-10-16 17:50:48.915887506 +0200 +++ new/src/hotspot/share/opto/phaseX.cpp 2018-10-16 17:50:40.430907012 +0200 @@ -1375,7 +1375,7 @@ assert(!(i < imax), "sanity"); } } else { - BarrierSet::barrier_set()->barrier_set_c2()->enqueue_useful_gc_barrier(_worklist, in); + BarrierSet::barrier_set()->barrier_set_c2()->enqueue_useful_gc_barrier(this, in); } if (ReduceFieldZeroing && dead->is_Load() && i == MemNode::Memory && in->is_Proj() && in->in(0) != NULL && in->in(0)->is_Initialize()) { @@ -2089,6 +2089,8 @@ default: break; } + + BarrierSet::barrier_set()->barrier_set_c2()->enqueue_useful_gc_barrier(igvn, old); } } --- old/src/hotspot/share/opto/subnode.cpp 2018-10-16 17:50:57.521867723 +0200 +++ new/src/hotspot/share/opto/subnode.cpp 2018-10-16 17:50:49.024887256 +0200 @@ -883,9 +883,7 @@ // LoadBarrier?(LoadP(LoadP(AddP(foo:Klass, #java_mirror)))) // or NULL if not matching. BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - if (bs->is_gc_barrier_node(n)) { n = bs->step_over_gc_barrier(n); - } if (n->Opcode() != Op_LoadP) return NULL; @@ -959,8 +957,14 @@ if (k1 && (k2 || conk2)) { Node* lhs = k1; Node* rhs = (k2 != NULL) ? k2 : conk2; - this->set_req(1, lhs); - this->set_req(2, rhs); + PhaseIterGVN* igvn = phase->is_IterGVN(); + if (igvn != NULL) { + set_req_X(1, lhs, igvn); + set_req_X(2, rhs, igvn); + } else { + set_req(1, lhs); + set_req(2, rhs); + } return this; } }