Search in sources :

Example 6 with WithExceptionNode

use of org.graalvm.compiler.nodes.WithExceptionNode in project graal by oracle.

the class OptimizeExceptionPathsPhase method walkBack.

private static void walkBack(ControlSinkNode sink, NodeBitMap exceptionPaths) {
    Deque<Node> worklist = new ArrayDeque<>();
    worklist.push(sink);
    while (!worklist.isEmpty()) {
        Node node = worklist.pop();
        Node predecessor = node.predecessor();
        /* Second loop to avoid the worklist while walking back within a block. */
        while (predecessor != null) {
            if ((predecessor instanceof IfNode || predecessor instanceof SwitchNode) && node instanceof AbstractBeginNode) {
                boolean allSuccessorsInExceptionPaths = true;
                for (Node sux : predecessor.successors()) {
                    if (sux != node && !exceptionPaths.contains(sux)) {
                        allSuccessorsInExceptionPaths = false;
                        break;
                    }
                }
                if (allSuccessorsInExceptionPaths) {
                    /*
                         * All successors of the control split go to an exception path, so keep
                         * walking backward.
                         */
                    for (Node sux : predecessor.successors()) {
                        exceptionPaths.clear(sux);
                    }
                } else {
                    exceptionPaths.mark(node);
                    break;
                }
            } else if (predecessor instanceof MergeNode) {
                for (ValueNode endNode : ((MergeNode) predecessor).cfgPredecessors()) {
                    worklist.push(endNode);
                }
                break;
            } else if (predecessor instanceof WithExceptionNode && node instanceof AbstractBeginNode) {
                if (node == ((WithExceptionNode) predecessor).exceptionEdge()) {
                    /*
                         * We are at the exception edge of the WithExceptionNode. It has the correct
                         * probability, so nothing to do.
                         */
                    break;
                } else {
                /*
                         * We are at the regular successor edge of the WithExceptionNode, keep
                         * walking back.
                         */
                }
            } else if (predecessor instanceof AbstractMergeNode || predecessor instanceof ControlSplitNode) {
                /* Any other split or merge is suspicious: we abort. */
                break;
            }
            node = predecessor;
            predecessor = node.predecessor();
        }
    }
}
Also used : AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) WithExceptionNode(org.graalvm.compiler.nodes.WithExceptionNode) DeadEndNode(org.graalvm.compiler.nodes.DeadEndNode) LoweredDeadEndNode(com.oracle.svm.core.graal.nodes.LoweredDeadEndNode) IfNode(org.graalvm.compiler.nodes.IfNode) BranchProbabilityNode(org.graalvm.compiler.nodes.extended.BranchProbabilityNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) SwitchNode(org.graalvm.compiler.nodes.extended.SwitchNode) UnwindNode(org.graalvm.compiler.nodes.UnwindNode) WithExceptionNode(org.graalvm.compiler.nodes.WithExceptionNode) Node(org.graalvm.compiler.graph.Node) MergeNode(org.graalvm.compiler.nodes.MergeNode) ControlSinkNode(org.graalvm.compiler.nodes.ControlSinkNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) IfNode(org.graalvm.compiler.nodes.IfNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) SwitchNode(org.graalvm.compiler.nodes.extended.SwitchNode) ArrayDeque(java.util.ArrayDeque) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 7 with WithExceptionNode

use of org.graalvm.compiler.nodes.WithExceptionNode in project graal by oracle.

the class RemoveUnwindPhase method run.

@Override
protected void run(StructuredGraph graph) {
    SharedMethod method = (SharedMethod) graph.method();
    if (method.isDeoptTarget()) {
        /*
             * Deoptimization targets need need to have an exception entry point for every invoke.
             * This decouples deoptimization from exception handling: the exception handling
             * mechanism can just deliver an exception to a deoptimized method without any checks.
             */
        return;
    }
    List<WithExceptionNode> withExceptionNodes = new ArrayList<>();
    List<BytecodeExceptionNode> bytecodeExceptionNodes = new ArrayList<>();
    for (UnwindNode node : graph.getNodes(UnwindNode.TYPE)) {
        walkBack(node.predecessor(), node, withExceptionNodes, bytecodeExceptionNodes, GraphUtil.unproxify(node.exception()), graph);
    }
    /*
         * Modify graph only after all suitable nodes with exceptions are found, to avoid problems
         * with deleted nodes during graph traversal.
         */
    for (WithExceptionNode node : withExceptionNodes) {
        if (node.isAlive()) {
            graph.getDebug().log(DebugContext.DETAILED_LEVEL, "Removing exception edge for: %s", node);
            node.replaceWithNonThrowing();
        }
    }
    for (BytecodeExceptionNode bytecodeExceptionNode : bytecodeExceptionNodes) {
        if (bytecodeExceptionNode.isAlive()) {
            graph.getDebug().log(DebugContext.DETAILED_LEVEL, "Converting a BytecodeException node to a ThrowBytecodeException node for: %s", bytecodeExceptionNode);
            convertToThrow(bytecodeExceptionNode);
        }
    }
}
Also used : WithExceptionNode(org.graalvm.compiler.nodes.WithExceptionNode) ThrowBytecodeExceptionNode(com.oracle.svm.core.graal.nodes.ThrowBytecodeExceptionNode) BytecodeExceptionNode(org.graalvm.compiler.nodes.extended.BytecodeExceptionNode) ArrayList(java.util.ArrayList) SharedMethod(com.oracle.svm.core.meta.SharedMethod) UnwindNode(org.graalvm.compiler.nodes.UnwindNode)

Example 8 with WithExceptionNode

use of org.graalvm.compiler.nodes.WithExceptionNode in project graal by oracle.

the class RemoveUnwindPhase method walkBack.

/**
 * We walk back from the {@link UnwindNode} to a {@link WithExceptionNode}. If the control flow
 * path only contains nodes white-listed in this method, then we know that we have a node that
 * just forwards the exception to the {@link UnwindNode}. Such nodes are rewritten to a variant
 * without an exception edge, i.e., no exception handler entry is created for such invokes.
 */
protected static void walkBack(Node n, Node successor, List<WithExceptionNode> withExceptionNodes, List<BytecodeExceptionNode> bytecodeExceptionNodes, ValueNode expectedExceptionNode, StructuredGraph graph) {
    if (n instanceof WithExceptionNode) {
        WithExceptionNode node = (WithExceptionNode) n;
        if (node.exceptionEdge() == successor) {
            withExceptionNodes.add(node);
        }
    } else if (n instanceof BytecodeExceptionNode || n instanceof ExceptionObjectNode) {
        if (n == expectedExceptionNode) {
            if (n instanceof BytecodeExceptionNode) {
                BytecodeExceptionNode node = (BytecodeExceptionNode) n;
                bytecodeExceptionNodes.add(node);
            } else {
                walkBack(n.predecessor(), n, withExceptionNodes, bytecodeExceptionNodes, expectedExceptionNode, graph);
            }
        } else {
            graph.getDebug().log(DebugContext.VERY_DETAILED_LEVEL, "Node %s does not flow to the corresponding Unwind. Bailing out.", n);
        }
    } else if (n instanceof MergeNode) {
        MergeNode merge = (MergeNode) n;
        if (merge.isPhiAtMerge(expectedExceptionNode)) {
            /* Propagate expected exception on each control path leading to the merge */
            PhiNode expectedExceptionForInput = (PhiNode) expectedExceptionNode;
            for (int input = 0; input < merge.forwardEndCount(); input++) {
                Node predecessor = merge.forwardEndAt(input);
                walkBack(predecessor, merge, withExceptionNodes, bytecodeExceptionNodes, GraphUtil.unproxify(expectedExceptionForInput.valueAt(input)), graph);
            }
        } else {
            for (ValueNode predecessor : merge.cfgPredecessors()) {
                walkBack(predecessor, merge, withExceptionNodes, bytecodeExceptionNodes, expectedExceptionNode, graph);
            }
        }
    } else if (n instanceof AbstractBeginNode || n instanceof AbstractEndNode) {
        walkBack(n.predecessor(), n, withExceptionNodes, bytecodeExceptionNodes, expectedExceptionNode, graph);
    }
}
Also used : MergeNode(org.graalvm.compiler.nodes.MergeNode) WithExceptionNode(org.graalvm.compiler.nodes.WithExceptionNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ThrowBytecodeExceptionNode(com.oracle.svm.core.graal.nodes.ThrowBytecodeExceptionNode) BytecodeExceptionNode(org.graalvm.compiler.nodes.extended.BytecodeExceptionNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) UnwindNode(org.graalvm.compiler.nodes.UnwindNode) ThrowBytecodeExceptionNode(com.oracle.svm.core.graal.nodes.ThrowBytecodeExceptionNode) WithExceptionNode(org.graalvm.compiler.nodes.WithExceptionNode) BytecodeExceptionNode(org.graalvm.compiler.nodes.extended.BytecodeExceptionNode) Node(org.graalvm.compiler.graph.Node) MergeNode(org.graalvm.compiler.nodes.MergeNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 9 with WithExceptionNode

use of org.graalvm.compiler.nodes.WithExceptionNode in project graal by oracle.

the class SubstrateGraphKit method appendWithUnwind.

/**
 * Appends the provided node to the control flow graph. The exception edge is connected to an
 * {@link UnwindNode}, i.e., the exception is not handled in this method.
 */
protected <T extends WithExceptionNode> T appendWithUnwind(T withExceptionNode, int bci) {
    WithExceptionNode appended = append(withExceptionNode);
    assert appended == withExceptionNode;
    if (withExceptionNode instanceof StateSplit) {
        StateSplit stateSplit = (StateSplit) withExceptionNode;
        stateSplit.setStateAfter(frameState.create(bci, stateSplit));
    }
    AbstractBeginNode noExceptionEdge = add(new BeginNode());
    withExceptionNode.setNext(noExceptionEdge);
    ExceptionObjectNode exceptionEdge = createExceptionObjectNode(frameState, bci);
    withExceptionNode.setExceptionEdge(exceptionEdge);
    assert lastFixedNode == null;
    lastFixedNode = exceptionEdge;
    append(new UnwindNode(exceptionEdge));
    assert lastFixedNode == null;
    lastFixedNode = noExceptionEdge;
    return withExceptionNode;
}
Also used : InvokeWithExceptionNode(org.graalvm.compiler.nodes.InvokeWithExceptionNode) WithExceptionNode(org.graalvm.compiler.nodes.WithExceptionNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) UnwindNode(org.graalvm.compiler.nodes.UnwindNode) StateSplit(org.graalvm.compiler.nodes.StateSplit) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 10 with WithExceptionNode

use of org.graalvm.compiler.nodes.WithExceptionNode in project graal by oracle.

the class EffectsClosure method processBlock.

@Override
protected BlockT processBlock(Block block, BlockT state) {
    if (!state.isDead()) {
        GraphEffectList effects = blockEffects.get(block);
        /*
             * If we enter an if branch that is known to be unreachable, we mark it as dead and
             * cease to do any more analysis on it. At merges, these dead branches will be ignored.
             */
        if (block.getBeginNode().predecessor() instanceof IfNode) {
            IfNode ifNode = (IfNode) block.getBeginNode().predecessor();
            LogicNode condition = ifNode.condition();
            Node alias = getScalarAlias(condition);
            if (alias instanceof LogicConstantNode) {
                LogicConstantNode constant = (LogicConstantNode) alias;
                boolean isTrueSuccessor = block.getBeginNode() == ifNode.trueSuccessor();
                if (constant.getValue() != isTrueSuccessor) {
                    state.markAsDead();
                    effects.killIfBranch(ifNode, constant.getValue());
                    return state;
                }
            }
        }
        OptionValues options = block.getBeginNode().getOptions();
        VirtualUtil.trace(options, debug, "\nBlock: %s, preds: %s, succ: %s (", block, block.getPredecessors(), block.getSuccessors());
        // a lastFixedNode is needed in case we want to insert fixed nodes
        FixedWithNextNode lastFixedNode = null;
        Iterable<? extends Node> nodes = schedule != null ? schedule.getBlockToNodesMap().get(block) : block.getNodes();
        for (Node node : nodes) {
            // reset the aliases (may be non-null due to iterative loop processing)
            aliases.set(node, null);
            if (node instanceof LoopExitNode) {
                LoopExitNode loopExit = (LoopExitNode) node;
                for (ProxyNode proxy : loopExit.proxies()) {
                    aliases.set(proxy, null);
                    changed |= processNode(proxy, state, effects, lastFixedNode) && isSignificantNode(node);
                }
                processLoopExit(loopExit, loopEntryStates.get(loopExit.loopBegin()), state, blockEffects.get(block));
            }
            Block exceptionEdgeToKill = node instanceof WithExceptionNode ? cfg.blockFor(((WithExceptionNode) node).exceptionEdge()) : null;
            boolean lastNodeChanged = processNode(node, state, effects, lastFixedNode) && isSignificantNode(node);
            changed |= lastNodeChanged;
            if (lastNodeChanged && exceptionEdgeToKill != null) {
                /*
                     * We deleted a exception node, per definition the exception edge died in that
                     * process, no need to process the exception edge
                     */
                if (state.exceptionEdgesToKill == null) {
                    state.exceptionEdgesToKill = EconomicSet.create();
                }
                state.exceptionEdgesToKill.add(exceptionEdgeToKill);
            }
            if (node instanceof FixedWithNextNode) {
                lastFixedNode = (FixedWithNextNode) node;
            }
            if (state.isDead()) {
                break;
            }
        }
        VirtualUtil.trace(options, debug, ")\n    end state: %s\n", state);
    }
    return state;
}
Also used : ProxyNode(org.graalvm.compiler.nodes.ProxyNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) OptionValues(org.graalvm.compiler.options.OptionValues) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) LogicConstantNode(org.graalvm.compiler.nodes.LogicConstantNode) AllocatedObjectNode(org.graalvm.compiler.nodes.virtual.AllocatedObjectNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) BoxNode(org.graalvm.compiler.nodes.extended.BoxNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) IfNode(org.graalvm.compiler.nodes.IfNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) CommitAllocationNode(org.graalvm.compiler.nodes.virtual.CommitAllocationNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) WithExceptionNode(org.graalvm.compiler.nodes.WithExceptionNode) Node(org.graalvm.compiler.graph.Node) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) LogicConstantNode(org.graalvm.compiler.nodes.LogicConstantNode) IfNode(org.graalvm.compiler.nodes.IfNode) WithExceptionNode(org.graalvm.compiler.nodes.WithExceptionNode) Block(org.graalvm.compiler.nodes.cfg.Block) LogicNode(org.graalvm.compiler.nodes.LogicNode)

Aggregations

WithExceptionNode (org.graalvm.compiler.nodes.WithExceptionNode)15 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)10 InvokeWithExceptionNode (org.graalvm.compiler.nodes.InvokeWithExceptionNode)9 UnwindNode (org.graalvm.compiler.nodes.UnwindNode)9 Node (org.graalvm.compiler.graph.Node)8 FixedNode (org.graalvm.compiler.nodes.FixedNode)8 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)8 ValueNode (org.graalvm.compiler.nodes.ValueNode)8 ExceptionObjectNode (org.graalvm.compiler.nodes.java.ExceptionObjectNode)8 PhiNode (org.graalvm.compiler.nodes.PhiNode)7 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)6 IfNode (org.graalvm.compiler.nodes.IfNode)6 MergeNode (org.graalvm.compiler.nodes.MergeNode)6 ControlSinkNode (org.graalvm.compiler.nodes.ControlSinkNode)5 LogicNode (org.graalvm.compiler.nodes.LogicNode)5 UnreachableBeginNode (org.graalvm.compiler.nodes.UnreachableBeginNode)5 FallbackInvokeWithExceptionNode (org.graalvm.compiler.replacements.nodes.FallbackInvokeWithExceptionNode)5 MacroWithExceptionNode (org.graalvm.compiler.replacements.nodes.MacroWithExceptionNode)5 BeginNode (org.graalvm.compiler.nodes.BeginNode)4 DeoptimizingNode (org.graalvm.compiler.nodes.DeoptimizingNode)4