diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index 924307976f2..1ea4556a6e8 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -1125,9 +1125,9 @@ bool CallStaticJavaNode::cmp( const Node &n ) const { Node* CallStaticJavaNode::Ideal(PhaseGVN* phase, bool can_reshape) { if (can_reshape && uncommon_trap_request() != 0) { - if (remove_useless_allocation(phase, in(0), in(TypeFunc::Memory), in(TypeFunc::Parms))) { + PhaseIterGVN* igvn = phase->is_IterGVN(); + if (remove_unknown_flat_array_load(igvn, in(0), in(TypeFunc::Memory), in(TypeFunc::Parms))) { if (!in(0)->is_Region()) { - PhaseIterGVN* igvn = phase->is_IterGVN(); igvn->replace_input_of(this, 0, phase->C->top()); } return this; @@ -1186,16 +1186,13 @@ int CallStaticJavaNode::extract_uncommon_trap_request(const Node* call) { return call->in(TypeFunc::Parms)->bottom_type()->is_int()->get_con(); } -bool CallStaticJavaNode::remove_useless_allocation(PhaseGVN *phase, Node* ctl, Node* mem, Node* unc_arg) { - // Split if can cause the flat array branch of an array load to - // end in an uncommon trap. In that case, the allocation of the - // loaded value and its initialization is useless. Eliminate it. use - // the jvm state of the allocation to create a new uncommon trap - // call at the load. +// Split if can cause the flat array branch of an array load with unknown type (see +// Parse::array_load) to end in an uncommon trap. In that case, the call to +// 'load_unknown_inline' is useless. Replace it with an uncommon trap with the same JVMState. +bool CallStaticJavaNode::remove_unknown_flat_array_load(PhaseIterGVN* igvn, Node* ctl, Node* mem, Node* unc_arg) { if (ctl == nullptr || ctl->is_top() || mem == nullptr || mem->is_top() || !mem->is_MergeMem()) { return false; } - PhaseIterGVN* igvn = phase->is_IterGVN(); if (ctl->is_Region()) { bool res = false; for (uint i = 1; i < ctl->req(); i++) { @@ -1206,17 +1203,17 @@ bool CallStaticJavaNode::remove_useless_allocation(PhaseGVN *phase, Node* ctl, N mms.set_memory(m->in(i)); } } - if (remove_useless_allocation(phase, ctl->in(i), mm, unc_arg)) { + if (remove_unknown_flat_array_load(igvn, ctl->in(i), mm, unc_arg)) { res = true; if (!ctl->in(i)->is_Region()) { - igvn->replace_input_of(ctl, i, phase->C->top()); + igvn->replace_input_of(ctl, i, igvn->C->top()); } } igvn->remove_dead_node(mm); } return res; } - // verify the control flow is ok + // Verify the control flow is ok Node* call = ctl; MemBarNode* membar = nullptr; for (;;) { @@ -1225,7 +1222,7 @@ bool CallStaticJavaNode::remove_useless_allocation(PhaseGVN *phase, Node* ctl, N } if (call->is_Proj() || call->is_Catch() || call->is_MemBar()) { call = call->in(0); - } else if (call->Opcode() == Op_CallStaticJava && + } else if (call->Opcode() == Op_CallStaticJava && !call->in(0)->is_top() && call->as_Call()->entry_point() == OptoRuntime::load_unknown_inline_Java()) { assert(call->in(0)->is_Proj() && call->in(0)->in(0)->is_MemBar(), "missing membar"); membar = call->in(0)->in(0)->as_MemBar(); @@ -1236,21 +1233,21 @@ bool CallStaticJavaNode::remove_useless_allocation(PhaseGVN *phase, Node* ctl, N } JVMState* jvms = call->jvms(); - if (phase->C->too_many_traps(jvms->method(), jvms->bci(), Deoptimization::trap_request_reason(uncommon_trap_request()))) { + if (igvn->C->too_many_traps(jvms->method(), jvms->bci(), Deoptimization::trap_request_reason(uncommon_trap_request()))) { return false; } - Node* alloc_mem = call->in(TypeFunc::Memory); - if (alloc_mem == nullptr || alloc_mem->is_top()) { + Node* call_mem = call->in(TypeFunc::Memory); + if (call_mem == nullptr || call_mem->is_top()) { return false; } - if (!alloc_mem->is_MergeMem()) { - alloc_mem = MergeMemNode::make(alloc_mem); - igvn->register_new_node_with_optimizer(alloc_mem); + if (!call_mem->is_MergeMem()) { + call_mem = MergeMemNode::make(call_mem); + igvn->register_new_node_with_optimizer(call_mem); } - // and that there's no unexpected side effect - for (MergeMemStream mms2(mem->as_MergeMem(), alloc_mem->as_MergeMem()); mms2.next_non_empty2(); ) { + // Verify that there's no unexpected side effect + for (MergeMemStream mms2(mem->as_MergeMem(), call_mem->as_MergeMem()); mms2.next_non_empty2(); ) { Node* m1 = mms2.is_empty() ? mms2.base_memory() : mms2.memory(); Node* m2 = mms2.memory2(); @@ -1280,8 +1277,8 @@ bool CallStaticJavaNode::remove_useless_allocation(PhaseGVN *phase, Node* ctl, N } } } - if (alloc_mem->outcnt() == 0) { - igvn->remove_dead_node(alloc_mem); + if (call_mem->outcnt() == 0) { + igvn->remove_dead_node(call_mem); } // Remove membar preceding the call @@ -1298,13 +1295,14 @@ bool CallStaticJavaNode::remove_useless_allocation(PhaseGVN *phase, Node* ctl, N unc->set_cnt(PROB_UNLIKELY_MAG(4)); unc->copy_call_debug_info(igvn, call->as_CallStaticJava()); - igvn->replace_input_of(call, 0, phase->C->top()); + // Replace the call with an uncommon trap + igvn->replace_input_of(call, 0, igvn->C->top()); igvn->register_new_node_with_optimizer(unc); - Node* ctrl = phase->transform(new ProjNode(unc, TypeFunc::Control)); - Node* halt = phase->transform(new HaltNode(ctrl, call->in(TypeFunc::FramePtr), "uncommon trap returned which should never happen")); - igvn->add_input_to(phase->C->root(), halt); + Node* ctrl = igvn->transform(new ProjNode(unc, TypeFunc::Control)); + Node* halt = igvn->transform(new HaltNode(ctrl, call->in(TypeFunc::FramePtr), "uncommon trap returned which should never happen")); + igvn->add_input_to(igvn->C->root(), halt); return true; } diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index 3605709e1f0..0d1720f6bbb 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -819,7 +819,7 @@ class CallStaticJavaNode : public CallJavaNode { virtual bool cmp( const Node &n ) const; virtual uint size_of() const; // Size is bigger - bool remove_useless_allocation(PhaseGVN *phase, Node* ctl, Node* mem, Node* unc_arg); + bool remove_unknown_flat_array_load(PhaseIterGVN* phase, Node* ctl, Node* mem, Node* unc_arg); public: CallStaticJavaNode(Compile* C, const TypeFunc* tf, address addr, ciMethod* method)