--- old/src/share/vm/opto/ifnode.cpp 2015-10-30 14:46:19.359964507 +0100 +++ new/src/share/vm/opto/ifnode.cpp 2015-10-30 14:46:19.287964504 +0100 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "ci/ciTypeFlow.hpp" #include "memory/allocation.inline.hpp" #include "opto/addnode.hpp" #include "opto/castnode.hpp" @@ -768,7 +769,8 @@ // Do this If and the dominating If both branch out to an uncommon trap bool IfNode::has_only_uncommon_traps(ProjNode* proj, ProjNode*& success, ProjNode*& fail, PhaseIterGVN* igvn) { ProjNode* otherproj = proj->other_if_proj(); - CallStaticJavaNode* dom_unc = otherproj->is_uncommon_trap_proj(Deoptimization::Reason_none); + // Dominating uncommon trap must have 'Reason_unstable_if' to ensure re-execution of folded Ifs + CallStaticJavaNode* dom_unc = otherproj->is_uncommon_trap_proj(Deoptimization::Reason_unstable_if); if (otherproj->outcnt() == 1 && dom_unc != NULL) { CallStaticJavaNode* unc = NULL; @@ -784,12 +786,28 @@ } else if (dom_unc->in(0) != otherproj || unc->in(0) != unc_proj) { return false; } + + // Check if the bci of the dominating uncommon trap dominates the bci + // of the dominated uncommon trap. Otherwise we may not re-execute + // the dominated check after deoptimization from the merged uncommon trap. + ciMethod* method = unc->jvms()->method(); + ciMethod* dom_method = dom_unc->jvms()->method(); + if (method != dom_method) { + return false; + } + ciTypeFlow* flow = dom_method->get_flow_analysis(); + int bci = unc->jvms()->bci(); + int dom_bci = dom_unc->jvms()->bci(); + if (!flow->is_dominated_by(bci, dom_bci)) { + return false; + } + // See merge_uncommon_traps: the reason of the uncommon trap // will be changed and the state of the dominating If will be // used. Checked that we didn't apply this transformation in a // previous compilation and it didn't cause too many traps - if (!igvn->C->too_many_traps(dom_unc->jvms()->method(), dom_unc->jvms()->bci(), Deoptimization::Reason_unstable_fused_if) && - !igvn->C->too_many_traps(dom_unc->jvms()->method(), dom_unc->jvms()->bci(), Deoptimization::Reason_range_check)) { + if (!igvn->C->too_many_traps(dom_method, dom_bci, Deoptimization::Reason_unstable_fused_if) && + !igvn->C->too_many_traps(dom_method, dom_bci, Deoptimization::Reason_range_check)) { success = unc_proj; fail = unc_proj->other_if_proj(); return true;