diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,8 +26,8 @@ import java.util.List; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.InputType; @@ -46,6 +46,8 @@ import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.LoopExitNode; import org.graalvm.compiler.nodes.ProxyNode; +import org.graalvm.compiler.nodes.StartNode; +import org.graalvm.compiler.nodes.StaticDeoptimizingNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; @@ -57,8 +59,6 @@ import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.DeoptimizationAction; -import jdk.vm.ci.meta.DeoptimizationReason; -import jdk.vm.ci.meta.JavaConstant; /** * This phase will find branches which always end with a {@link DeoptimizeNode} and replace their @@ -77,18 +77,16 @@ @SuppressWarnings("try") protected void run(final StructuredGraph graph, PhaseContext context) { assert graph.hasValueProxies() : "ConvertDeoptimizeToGuardPhase always creates proxies"; + assert !graph.getGuardsStage().areFrameStatesAtDeopts() : graph.getGuardsStage(); for (DeoptimizeNode d : graph.getNodes(DeoptimizeNode.TYPE)) { assert d.isAlive(); - // Can only aggressively move deoptimization point if their action implies that - // the deoptimization will not be triggered again. Example for such action is - // reprofiling or recompiling with less aggressive options. - if (d.action() != DeoptimizationAction.None) { - try (DebugCloseable closable = d.withNodeSourcePosition()) { - visitDeoptBegin(AbstractBeginNode.prevBegin(d), d.action(), d.reason(), d.getSpeculation(), graph, context != null ? context.getLowerer() : null); - } + if (d.getAction() == DeoptimizationAction.None) { + continue; } - + try (DebugCloseable closable = d.withNodeSourcePosition()) { + propagateFixed(d, d, context != null ? context.getLowerer() : null); + } } if (context != null) { @@ -154,71 +152,73 @@ ys = yPhi.valueAt(mergePredecessor).asConstant(); } if (xs != null && ys != null && compare.condition().foldCondition(xs, ys, context.getConstantReflection(), compare.unorderedIsTrue()) == fixedGuard.isNegated()) { - visitDeoptBegin(AbstractBeginNode.prevBegin(mergePredecessor), fixedGuard.getAction(), fixedGuard.getReason(), fixedGuard.getSpeculation(), fixedGuard.graph(), context.getLowerer()); + propagateFixed(mergePredecessor, fixedGuard, context.getLowerer()); } } } - private void visitDeoptBegin(AbstractBeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, JavaConstant speculation, StructuredGraph graph, - LoweringProvider loweringProvider) { - if (deoptBegin.predecessor() instanceof AbstractBeginNode) { - /* - * Walk up chains of LoopExitNodes to the "real" BeginNode that leads to deoptimization. - */ - visitDeoptBegin((AbstractBeginNode) deoptBegin.predecessor(), deoptAction, deoptReason, speculation, graph, loweringProvider); - return; - } + private void propagateFixed(FixedNode from, StaticDeoptimizingNode deopt, LoweringProvider loweringProvider) { + Node current = from; + while (current != null) { + if (GraalOptions.GuardPriorities.getValue(from.getOptions()) && current instanceof FixedGuardNode) { + FixedGuardNode otherGuard = (FixedGuardNode) current; + if (otherGuard.computePriority().isHigherPriorityThan(deopt.computePriority())) { + moveAsDeoptAfter(otherGuard, deopt); + return; + } + } else if (current instanceof AbstractBeginNode) { + if (current instanceof AbstractMergeNode) { + AbstractMergeNode mergeNode = (AbstractMergeNode) current; + FixedNode next = mergeNode.next(); + while (mergeNode.isAlive()) { + AbstractEndNode end = mergeNode.forwardEnds().first(); + propagateFixed(end, deopt, loweringProvider); + } + assert next.isAlive(); + propagateFixed(next, deopt, loweringProvider); + return; + } else if (current.predecessor() instanceof IfNode) { + IfNode ifNode = (IfNode) current.predecessor(); + StructuredGraph graph = ifNode.graph(); + LogicNode conditionNode = ifNode.condition(); + boolean negateGuardCondition = current == ifNode.trueSuccessor(); + FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.getReason(), deopt.getAction(), deopt.getSpeculation(), negateGuardCondition)); + FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor(); + AbstractBeginNode survivingSuccessor; + if (negateGuardCondition) { + survivingSuccessor = ifNode.falseSuccessor(); + } else { + survivingSuccessor = ifNode.trueSuccessor(); + } + graph.removeSplitPropagate(ifNode, survivingSuccessor); - DebugContext debug = deoptBegin.getDebug(); - if (deoptBegin instanceof AbstractMergeNode) { - AbstractMergeNode mergeNode = (AbstractMergeNode) deoptBegin; - debug.log("Visiting %s", mergeNode); - FixedNode next = mergeNode.next(); - while (mergeNode.isAlive()) { - AbstractEndNode end = mergeNode.forwardEnds().first(); - AbstractBeginNode newBeginNode = AbstractBeginNode.prevBegin(end); - visitDeoptBegin(newBeginNode, deoptAction, deoptReason, speculation, graph, loweringProvider); + Node newGuard = guard; + if (survivingSuccessor instanceof LoopExitNode) { + newGuard = ProxyNode.forGuard(guard, (LoopExitNode) survivingSuccessor, graph); + } + survivingSuccessor.replaceAtUsages(InputType.Guard, newGuard); + + graph.getDebug().log("Converting deopt on %-5s branch of %s to guard for remaining branch %s.", negateGuardCondition, ifNode, survivingSuccessor); + FixedNode next = pred.next(); + pred.setNext(guard); + guard.setNext(next); + SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, null, false, graph.getAssumptions(), graph.getOptions(), loweringProvider); + survivingSuccessor.simplify(simplifierTool); + return; + } else if (current.predecessor() == null || current.predecessor() instanceof ControlSplitNode) { + assert current.predecessor() != null || (current instanceof StartNode && current == ((AbstractBeginNode) current).graph().start()); + moveAsDeoptAfter((AbstractBeginNode) current, deopt); + return; + } } - assert next.isAlive(); - AbstractBeginNode newBeginNode = AbstractBeginNode.prevBegin(next); - visitDeoptBegin(newBeginNode, deoptAction, deoptReason, speculation, graph, loweringProvider); - return; - } else if (deoptBegin.predecessor() instanceof IfNode) { - IfNode ifNode = (IfNode) deoptBegin.predecessor(); - LogicNode conditionNode = ifNode.condition(); - FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deoptReason, deoptAction, speculation, deoptBegin == ifNode.trueSuccessor())); - FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor(); - AbstractBeginNode survivingSuccessor; - if (deoptBegin == ifNode.trueSuccessor()) { - survivingSuccessor = ifNode.falseSuccessor(); - } else { - survivingSuccessor = ifNode.trueSuccessor(); - } - graph.removeSplitPropagate(ifNode, survivingSuccessor); + current = current.predecessor(); + } + } - Node newGuard = guard; - if (survivingSuccessor instanceof LoopExitNode) { - newGuard = ProxyNode.forGuard(guard, (LoopExitNode) survivingSuccessor, graph); - } - survivingSuccessor.replaceAtUsages(InputType.Guard, newGuard); - - debug.log("Converting deopt on %-5s branch of %s to guard for remaining branch %s.", deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, survivingSuccessor); - FixedNode next = pred.next(); - pred.setNext(guard); - guard.setNext(next); - SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, null, false, graph.getAssumptions(), graph.getOptions(), loweringProvider); - survivingSuccessor.simplify(simplifierTool); - return; - } - - // We could not convert the control split - at least cut off control flow after the split. - FixedWithNextNode deoptPred = deoptBegin; - FixedNode next = deoptPred.next(); - - if (!(next instanceof DeoptimizeNode)) { - DeoptimizeNode newDeoptNode = graph.add(new DeoptimizeNode(deoptAction, deoptReason, speculation)); - deoptPred.setNext(newDeoptNode); - assert deoptPred == newDeoptNode.predecessor(); + private static void moveAsDeoptAfter(FixedWithNextNode node, StaticDeoptimizingNode deopt) { + FixedNode next = node.next(); + if (next != deopt.asNode()) { + node.setNext(node.graph().add(new DeoptimizeNode(deopt.getAction(), deopt.getReason(), deopt.getSpeculation()))); GraphUtil.killCFG(next); } }