Search in sources :

Example 6 with LoweredDeadEndNode

use of com.oracle.svm.core.graal.nodes.LoweredDeadEndNode in project graal by oracle.

the class OptimizeExceptionPathsPhase method run.

@Override
protected void run(StructuredGraph graph) {
    /*
         * First walk back from all exceptional control flow sinks to a control flow split that also
         * goes to a "regular" return.
         */
    NodeBitMap exceptionPaths = new NodeBitMap(graph);
    for (UnwindNode unwind : graph.getNodes(UnwindNode.TYPE)) {
        walkBack(unwind, exceptionPaths);
    }
    for (DeadEndNode deadEnd : graph.getNodes(DeadEndNode.TYPE)) {
        walkBack(deadEnd, exceptionPaths);
    }
    for (LoweredDeadEndNode deadEnd : graph.getNodes(LoweredDeadEndNode.TYPE)) {
        walkBack(deadEnd, exceptionPaths);
    }
    /* Now that we know all control flow splits, we modify the branch probabilities. */
    for (Node n : exceptionPaths) {
        AbstractBeginNode exceptionBegin = (AbstractBeginNode) n;
        ControlSplitNode controlSplitNode = (ControlSplitNode) exceptionBegin.predecessor();
        /*
             * Only overwrite the branch probability if it comes from non-profiled sources. If we
             * have proper PGO information that the exception edge is used, it deserves to be
             * optimized.
             */
        if (controlSplitNode.getProfileData().getProfileSource() != ProfileData.ProfileSource.PROFILED) {
            controlSplitNode.setProbability(exceptionBegin, BranchProbabilityNode.EXTREMELY_SLOW_PATH_PROFILE);
        }
    }
}
Also used : NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) 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) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) UnwindNode(org.graalvm.compiler.nodes.UnwindNode) LoweredDeadEndNode(com.oracle.svm.core.graal.nodes.LoweredDeadEndNode) DeadEndNode(org.graalvm.compiler.nodes.DeadEndNode) LoweredDeadEndNode(com.oracle.svm.core.graal.nodes.LoweredDeadEndNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 7 with LoweredDeadEndNode

use of com.oracle.svm.core.graal.nodes.LoweredDeadEndNode in project graal by oracle.

the class HostedBciBlockMapping method insertDeoptNode.

/**
 * Inserts either a DeoptEntryNode or DeoptProxyAnchorNode into the graph.
 */
private void insertDeoptNode(HostedBciBlockMapping.DeoptEntryInsertionPoint deopt) {
    /* Ensuring current frameState matches the expectations of the DeoptEntryInsertionPoint. */
    if (deopt instanceof HostedBciBlockMapping.DeoptBciBlock) {
        assert !frameState.rethrowException();
    } else {
        assert deopt instanceof HostedBciBlockMapping.DeoptExceptionDispatchBlock;
        assert frameState.rethrowException();
    }
    DeoptEntrySupport deoptNode = graph.add(deopt.isProxy() ? new DeoptProxyAnchorNode() : new DeoptEntryNode());
    FrameState stateAfter = frameState.create(deopt.frameStateBci(), deoptNode);
    deoptNode.setStateAfter(stateAfter);
    if (lastInstr != null) {
        lastInstr.setNext(deoptNode.asFixedNode());
    }
    if (deopt.isProxy()) {
        lastInstr = (DeoptProxyAnchorNode) deoptNode;
    } else {
        assert !deopt.duringCall() : "Implicit deopt entries from invokes cannot have explicit deopt entries.";
        DeoptEntryNode deoptEntryNode = (DeoptEntryNode) deoptNode;
        deoptEntryNode.setNext(graph.add(new DeoptEntryBeginNode()));
        /*
             * DeoptEntries for positions not during an exception dispatch (rethrowException) also
             * must be linked to their exception target.
             */
        if (!deopt.rethrowException()) {
            /*
                 * Saving frameState so that different modifications can be made for next() and
                 * exceptionEdge().
                 */
            FrameStateBuilder originalFrameState = frameState.copy();
            /* Creating exception object and its state after. */
            ExceptionObjectNode newExceptionObject = graph.add(new ExceptionObjectNode(getMetaAccess()));
            frameState.clearStack();
            frameState.push(JavaKind.Object, newExceptionObject);
            frameState.setRethrowException(true);
            int bci = ((HostedBciBlockMapping.DeoptBciBlock) deopt).getStartBci();
            newExceptionObject.setStateAfter(frameState.create(bci, newExceptionObject));
            deoptEntryNode.setExceptionEdge(newExceptionObject);
            /* Inserting proxies for the exception edge. */
            insertProxies(newExceptionObject, frameState);
            /* Linking exception object to exception target. */
            newExceptionObject.setNext(handleException(newExceptionObject, bci, false));
            /* Now restoring FrameState so proxies can be inserted for the next() edge. */
            frameState = originalFrameState;
        } else {
            /* Otherwise, indicate that the exception edge is not reachable. */
            AbstractBeginNode newExceptionEdge = graph.add(new UnreachableBeginNode());
            newExceptionEdge.setNext(graph.add(new LoweredDeadEndNode()));
            deoptEntryNode.setExceptionEdge(newExceptionEdge);
        }
        /* Correctly setting last instruction. */
        lastInstr = deoptEntryNode.next();
    }
    insertProxies(deoptNode.asFixedNode(), frameState);
}
Also used : ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) UnreachableBeginNode(org.graalvm.compiler.nodes.UnreachableBeginNode) FrameState(org.graalvm.compiler.nodes.FrameState) LoweredDeadEndNode(com.oracle.svm.core.graal.nodes.LoweredDeadEndNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) DeoptProxyAnchorNode(com.oracle.svm.core.graal.nodes.DeoptProxyAnchorNode) DeoptEntryNode(com.oracle.svm.core.graal.nodes.DeoptEntryNode) DeoptEntryBeginNode(com.oracle.svm.core.graal.nodes.DeoptEntryBeginNode) DeoptEntrySupport(com.oracle.svm.core.graal.nodes.DeoptEntrySupport) FrameStateBuilder(org.graalvm.compiler.java.FrameStateBuilder)

Example 8 with LoweredDeadEndNode

use of com.oracle.svm.core.graal.nodes.LoweredDeadEndNode in project graal by oracle.

the class CEntryPointSupport method registerEntryPointActionsPlugins.

private static void registerEntryPointActionsPlugins(InvocationPlugins plugins) {
    Registration r = new Registration(plugins, CEntryPointActions.class);
    r.register(new RequiredInvocationPlugin("enterCreateIsolate", CEntryPointCreateIsolateParameters.class) {

        @Override
        public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode parameters) {
            b.addPush(JavaKind.Int, CEntryPointEnterNode.createIsolate(parameters));
            return true;
        }
    });
    r.register(new RequiredInvocationPlugin("enterAttachThread", Isolate.class, boolean.class) {

        @Override
        public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode isolate, ValueNode ensureJavaThreadNode) {
            if (!ensureJavaThreadNode.isConstant()) {
                b.bailout("Parameter ensureJavaThread of enterAttachThread must be a compile time constant");
            }
            b.addPush(JavaKind.Int, CEntryPointEnterNode.attachThread(isolate, ensureJavaThreadNode.asJavaConstant().asInt() != 0, false));
            return true;
        }
    });
    r.register(new RequiredInvocationPlugin("enter", IsolateThread.class) {

        @Override
        public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode thread) {
            b.addPush(JavaKind.Int, CEntryPointEnterNode.enter(thread));
            return true;
        }
    });
    r.register(new RequiredInvocationPlugin("enterIsolate", Isolate.class) {

        @Override
        public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode isolate) {
            b.addPush(JavaKind.Int, CEntryPointEnterNode.enterIsolate(isolate));
            return true;
        }
    });
    r.register(new RequiredInvocationPlugin("enterAttachThreadFromCrashHandler", Isolate.class) {

        @Override
        public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode isolate) {
            b.addPush(JavaKind.Int, CEntryPointEnterNode.attachThread(isolate, false, true));
            return true;
        }
    });
    r.register(new RequiredInvocationPlugin("leave") {

        @Override
        public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
            StateSplitProxyNode proxy = new StateSplitProxyNode(null);
            b.add(proxy);
            b.setStateAfter(proxy);
            b.addPush(JavaKind.Int, new CEntryPointLeaveNode(LeaveAction.Leave));
            return true;
        }
    });
    r.register(new RequiredInvocationPlugin("leaveDetachThread") {

        @Override
        public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
            StateSplitProxyNode proxy = new StateSplitProxyNode(null);
            b.add(proxy);
            b.setStateAfter(proxy);
            b.addPush(JavaKind.Int, new CEntryPointLeaveNode(LeaveAction.DetachThread));
            return true;
        }
    });
    r.register(new RequiredInvocationPlugin("leaveTearDownIsolate") {

        @Override
        public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
            StateSplitProxyNode proxy = new StateSplitProxyNode(null);
            b.add(proxy);
            b.setStateAfter(proxy);
            b.addPush(JavaKind.Int, new CEntryPointLeaveNode(LeaveAction.TearDownIsolate));
            return true;
        }
    });
    r.register(new RequiredInvocationPlugin("failFatally", int.class, CCharPointer.class) {

        @Override
        public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2) {
            b.add(new CEntryPointUtilityNode(UtilityAction.FailFatally, arg1, arg2));
            /*
                 * FailFatally does not return, so we can cut out any control flow afterwards and
                 * set the probability of the IfNode that leads to this branch.
                 */
            LoweredDeadEndNode deadEndNode = b.add(new LoweredDeadEndNode());
            AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(deadEndNode);
            if (prevBegin != null && prevBegin.predecessor() instanceof IfNode) {
                ((IfNode) prevBegin.predecessor()).setProbability(prevBegin, BranchProbabilityNode.EXTREMELY_SLOW_PATH_PROFILE);
            }
            return true;
        }
    });
    r.register(new RequiredInvocationPlugin("isCurrentThreadAttachedTo", Isolate.class) {

        @Override
        public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode isolate) {
            b.addPush(JavaKind.Boolean, new CEntryPointUtilityNode(UtilityAction.IsAttached, isolate));
            return true;
        }
    });
}
Also used : RequiredInvocationPlugin(org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin) CEntryPointUtilityNode(com.oracle.svm.core.graal.nodes.CEntryPointUtilityNode) IfNode(org.graalvm.compiler.nodes.IfNode) LoweredDeadEndNode(com.oracle.svm.core.graal.nodes.LoweredDeadEndNode) CEntryPointLeaveNode(com.oracle.svm.core.graal.nodes.CEntryPointLeaveNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) IsolateThread(org.graalvm.nativeimage.IsolateThread) GraphBuilderContext(org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext) Registration(org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration) CEntryPointCreateIsolateParameters(com.oracle.svm.core.c.function.CEntryPointCreateIsolateParameters) StateSplitProxyNode(org.graalvm.compiler.nodes.extended.StateSplitProxyNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Isolate(org.graalvm.nativeimage.Isolate) CurrentIsolate(org.graalvm.nativeimage.CurrentIsolate) ResolvedJavaMethod(jdk.vm.ci.meta.ResolvedJavaMethod) CCharPointer(org.graalvm.nativeimage.c.type.CCharPointer)

Example 9 with LoweredDeadEndNode

use of com.oracle.svm.core.graal.nodes.LoweredDeadEndNode in project graal by oracle.

the class GraphPrepareMetaAccessExtensionProvider method registerDeoptEntries.

private static void registerDeoptEntries(CallTreeNode node) {
    for (FrameState frameState : node.graph.getNodes(FrameState.TYPE)) {
        if (frameState.hasExactlyOneUsage()) {
            Node usage = frameState.usages().first();
            if (node.level > 0 && usage == node.graph.start()) {
                /*
                     * During method inlining, the FrameState associated with the StartNode
                     * disappears. Therefore, this frame state cannot be a deoptimization target.
                     */
                continue;
            } else if (usage instanceof Invoke && ((Invoke) usage).stateAfter() == frameState) {
                /*
                     * If the FrameState is followed immediately by a dead end, then this state can
                     * never be reached and does not need to be registered.
                     */
                FixedNode next = ((Invoke) usage).next();
                while (next instanceof AbstractBeginNode) {
                    next = ((AbstractBeginNode) next).next();
                }
                if (next instanceof LoweredDeadEndNode) {
                    continue;
                }
            }
        }
        /*
             * We need to make sure that all inlined caller frames are available for deoptimization
             * too.
             */
        for (FrameState inlineState = frameState; inlineState != null; inlineState = inlineState.outerFrameState()) {
            if (inlineState.bci >= 0) {
                CompilationInfoSupport.singleton().registerDeoptEntry(inlineState);
            }
        }
    }
    for (Node n : node.graph.getNodes()) {
        /*
             * graph.getInvokes() only iterates invokes that have a MethodCallTarget, so by using it
             * we would miss invocations that are already intrinsified to an indirect call.
             */
        if (n instanceof Invoke) {
            Invoke invoke = (Invoke) n;
            /*
                 * The FrameState for the invoke (which is visited by the above loop) is the state
                 * after the call (where deoptimization that happens after the call has returned
                 * will continue execution). We also need to register the state during the call
                 * (where deoptimization while the call is on the stack will continue execution).
                 *
                 * Note that the bci of the Invoke and the bci of the FrameState of the Invoke are
                 * different: the Invoke has the bci of the invocation bytecode, the FrameState has
                 * the bci of the next bytecode after the invoke.
                 */
            FrameState stateDuring = invoke.stateAfter().duplicateModifiedDuringCall(invoke.bci(), invoke.asNode().getStackKind());
            assert stateDuring.duringCall() && !stateDuring.rethrowException();
            CompilationInfoSupport.singleton().registerDeoptEntry(stateDuring);
        }
    }
}
Also used : LoweredDeadEndNode(com.oracle.svm.core.graal.nodes.LoweredDeadEndNode) StackValueNode(com.oracle.svm.core.graal.stackvalue.StackValueNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) LogicConstantNode(org.graalvm.compiler.nodes.LogicConstantNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Node(org.graalvm.compiler.graph.Node) FixedNode(org.graalvm.compiler.nodes.FixedNode) FrameState(org.graalvm.compiler.nodes.FrameState) LoweredDeadEndNode(com.oracle.svm.core.graal.nodes.LoweredDeadEndNode) Invoke(org.graalvm.compiler.nodes.Invoke) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 10 with LoweredDeadEndNode

use of com.oracle.svm.core.graal.nodes.LoweredDeadEndNode in project graal by oracle.

the class ReflectionGraphKit method emitInvocationTargetException.

public void emitInvocationTargetException() {
    AbstractMergeNode merge = continueWithMerge(invocationTargetExceptionPaths);
    ValueNode exception = createPhi(invocationTargetExceptionPaths, merge);
    ResolvedJavaMethod throwInvocationTargetException = FactoryMethodSupport.singleton().lookup((UniverseMetaAccess) getMetaAccess(), getMetaAccess().lookupJavaMethod(invocationTargetExceptionConstructor), true);
    createJavaCallWithExceptionAndUnwind(CallTargetNode.InvokeKind.Static, throwInvocationTargetException, exception);
    append(new LoweredDeadEndNode());
}
Also used : ValueNode(org.graalvm.compiler.nodes.ValueNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) LoweredDeadEndNode(com.oracle.svm.core.graal.nodes.LoweredDeadEndNode) ResolvedJavaMethod(jdk.vm.ci.meta.ResolvedJavaMethod)

Aggregations

LoweredDeadEndNode (com.oracle.svm.core.graal.nodes.LoweredDeadEndNode)10 ValueNode (org.graalvm.compiler.nodes.ValueNode)7 ResolvedJavaMethod (jdk.vm.ci.meta.ResolvedJavaMethod)5 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)4 CEntryPointLeaveNode (com.oracle.svm.core.graal.nodes.CEntryPointLeaveNode)2 Node (org.graalvm.compiler.graph.Node)2 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)2 FixedNode (org.graalvm.compiler.nodes.FixedNode)2 FrameState (org.graalvm.compiler.nodes.FrameState)2 IfNode (org.graalvm.compiler.nodes.IfNode)2 InvokeWithExceptionNode (org.graalvm.compiler.nodes.InvokeWithExceptionNode)2 Uninterruptible (com.oracle.svm.core.annotate.Uninterruptible)1 CEntryPointCreateIsolateParameters (com.oracle.svm.core.c.function.CEntryPointCreateIsolateParameters)1 CEntryPointUtilityNode (com.oracle.svm.core.graal.nodes.CEntryPointUtilityNode)1 DeoptEntryBeginNode (com.oracle.svm.core.graal.nodes.DeoptEntryBeginNode)1 DeoptEntryNode (com.oracle.svm.core.graal.nodes.DeoptEntryNode)1 DeoptEntrySupport (com.oracle.svm.core.graal.nodes.DeoptEntrySupport)1 DeoptProxyAnchorNode (com.oracle.svm.core.graal.nodes.DeoptProxyAnchorNode)1 StackValueNode (com.oracle.svm.core.graal.stackvalue.StackValueNode)1 SubstrateMethodCallTargetNode (com.oracle.svm.core.nodes.SubstrateMethodCallTargetNode)1