Search in sources :

Example 6 with AbstractBeginNode

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

the class InliningUtil method finishInlining.

private static ValueNode finishInlining(Invoke invoke, StructuredGraph graph, FixedNode firstNode, List<ReturnNode> returnNodes, UnwindNode unwindNode, Assumptions inlinedAssumptions, StructuredGraph inlineGraph) {
    FixedNode invokeNode = invoke.asNode();
    FrameState stateAfter = invoke.stateAfter();
    assert stateAfter == null || stateAfter.isAlive();
    invokeNode.replaceAtPredecessor(firstNode);
    if (invoke instanceof InvokeWithExceptionNode) {
        InvokeWithExceptionNode invokeWithException = ((InvokeWithExceptionNode) invoke);
        if (unwindNode != null && unwindNode.isAlive()) {
            assert unwindNode.predecessor() != null;
            assert invokeWithException.exceptionEdge().successors().count() == 1;
            ExceptionObjectNode obj = (ExceptionObjectNode) invokeWithException.exceptionEdge();
            obj.replaceAtUsages(unwindNode.exception());
            Node n = obj.next();
            obj.setNext(null);
            unwindNode.replaceAndDelete(n);
            obj.replaceAtPredecessor(null);
            obj.safeDelete();
        } else {
            invokeWithException.killExceptionEdge();
        }
        // get rid of memory kill
        AbstractBeginNode begin = invokeWithException.next();
        if (begin instanceof KillingBeginNode) {
            AbstractBeginNode newBegin = new BeginNode();
            graph.addAfterFixed(begin, graph.add(newBegin));
            begin.replaceAtUsages(newBegin);
            graph.removeFixed(begin);
        }
    } else {
        if (unwindNode != null && unwindNode.isAlive()) {
            DeoptimizeNode deoptimizeNode = addDeoptimizeNode(graph, DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler);
            unwindNode.replaceAndDelete(deoptimizeNode);
        }
    }
    ValueNode returnValue;
    if (!returnNodes.isEmpty()) {
        FixedNode n = invoke.next();
        invoke.setNext(null);
        if (returnNodes.size() == 1) {
            ReturnNode returnNode = returnNodes.get(0);
            returnValue = returnNode.result();
            invokeNode.replaceAtUsages(returnValue);
            returnNode.replaceAndDelete(n);
        } else {
            MergeNode merge = graph.add(new MergeNode());
            merge.setStateAfter(stateAfter);
            returnValue = mergeReturns(merge, returnNodes);
            invokeNode.replaceAtUsages(returnValue);
            if (merge.isPhiAtMerge(returnValue)) {
                fixFrameStates(graph, merge, (PhiNode) returnValue);
            }
            merge.setNext(n);
        }
    } else {
        returnValue = null;
        invokeNode.replaceAtUsages(null);
        GraphUtil.killCFG(invoke.next());
    }
    // Copy assumptions from inlinee to caller
    Assumptions assumptions = graph.getAssumptions();
    if (assumptions != null) {
        if (inlinedAssumptions != null) {
            assumptions.record(inlinedAssumptions);
        }
    } else {
        assert inlinedAssumptions == null : String.format("cannot inline graph (%s) which makes assumptions into a graph (%s) that doesn't", inlineGraph, graph);
    }
    // Copy inlined methods from inlinee to caller
    graph.updateMethods(inlineGraph);
    // Update the set of accessed fields
    if (GraalOptions.GeneratePIC.getValue(graph.getOptions())) {
        graph.updateFields(inlineGraph);
    }
    if (inlineGraph.hasUnsafeAccess()) {
        graph.markUnsafeAccess();
    }
    assert inlineGraph.getSpeculationLog() == null || inlineGraph.getSpeculationLog() == graph.getSpeculationLog() : "Only the root graph should have a speculation log";
    return returnValue;
}
Also used : AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) MonitorIdNode(org.graalvm.compiler.nodes.java.MonitorIdNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) ReturnNode(org.graalvm.compiler.nodes.ReturnNode) CallTargetNode(org.graalvm.compiler.nodes.CallTargetNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) PiNode(org.graalvm.compiler.nodes.PiNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) MonitorExitNode(org.graalvm.compiler.nodes.java.MonitorExitNode) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) GuardingNode(org.graalvm.compiler.nodes.extended.GuardingNode) KillingBeginNode(org.graalvm.compiler.nodes.KillingBeginNode) StartNode(org.graalvm.compiler.nodes.StartNode) InvokeWithExceptionNode(org.graalvm.compiler.nodes.InvokeWithExceptionNode) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) InvokeNode(org.graalvm.compiler.nodes.InvokeNode) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) DeoptimizeNode(org.graalvm.compiler.nodes.DeoptimizeNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) UnwindNode(org.graalvm.compiler.nodes.UnwindNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) ForeignCallNode(org.graalvm.compiler.nodes.extended.ForeignCallNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) FrameState(org.graalvm.compiler.nodes.FrameState) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) ReturnNode(org.graalvm.compiler.nodes.ReturnNode) InvokeWithExceptionNode(org.graalvm.compiler.nodes.InvokeWithExceptionNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) KillingBeginNode(org.graalvm.compiler.nodes.KillingBeginNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Assumptions(jdk.vm.ci.meta.Assumptions) KillingBeginNode(org.graalvm.compiler.nodes.KillingBeginNode) DeoptimizeNode(org.graalvm.compiler.nodes.DeoptimizeNode)

Example 7 with AbstractBeginNode

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

the class MultiTypeGuardInlineInfo method createInvocationBlock.

private static AbstractBeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, AbstractMergeNode returnMerge, PhiNode returnValuePhi, AbstractMergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining) {
    Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining);
    AbstractBeginNode calleeEntryNode = graph.add(new BeginNode());
    calleeEntryNode.setNext(duplicatedInvoke.asNode());
    EndNode endNode = graph.add(new EndNode());
    duplicatedInvoke.setNext(endNode);
    returnMerge.addForwardEnd(endNode);
    if (returnValuePhi != null) {
        returnValuePhi.addInput(duplicatedInvoke.asNode());
    }
    return calleeEntryNode;
}
Also used : EndNode(org.graalvm.compiler.nodes.EndNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) Invoke(org.graalvm.compiler.nodes.Invoke) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 8 with AbstractBeginNode

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

the class MultiTypeGuardInlineInfo method inlineMultipleMethods.

private EconomicSet<Node> inlineMultipleMethods(StructuredGraph graph, Providers providers) {
    int numberOfMethods = concretes.size();
    FixedNode continuation = invoke.next();
    // setup merge and phi nodes for results and exceptions
    AbstractMergeNode returnMerge = graph.add(new MergeNode());
    returnMerge.setStateAfter(invoke.stateAfter());
    PhiNode returnValuePhi = null;
    if (invoke.asNode().getStackKind() != JavaKind.Void) {
        returnValuePhi = graph.addWithoutUnique(new ValuePhiNode(invoke.asNode().stamp(NodeView.DEFAULT).unrestricted(), returnMerge));
    }
    AbstractMergeNode exceptionMerge = null;
    PhiNode exceptionObjectPhi = null;
    if (invoke instanceof InvokeWithExceptionNode) {
        InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke;
        ExceptionObjectNode exceptionEdge = (ExceptionObjectNode) invokeWithException.exceptionEdge();
        exceptionMerge = graph.add(new MergeNode());
        FixedNode exceptionSux = exceptionEdge.next();
        graph.addBeforeFixed(exceptionSux, exceptionMerge);
        exceptionObjectPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(JavaKind.Object), exceptionMerge));
        exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(invoke.stateAfter().bci, true, JavaKind.Object, new JavaKind[] { JavaKind.Object }, new ValueNode[] { exceptionObjectPhi }));
    }
    // create one separate block for each invoked method
    AbstractBeginNode[] successors = new AbstractBeginNode[numberOfMethods + 1];
    for (int i = 0; i < numberOfMethods; i++) {
        successors[i] = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, true);
    }
    // create the successor for an unknown type
    FixedNode unknownTypeSux;
    if (shouldFallbackToInvoke()) {
        unknownTypeSux = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, false);
    } else {
        unknownTypeSux = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated));
    }
    successors[successors.length - 1] = BeginNode.begin(unknownTypeSux);
    // replace the invoke exception edge
    if (invoke instanceof InvokeWithExceptionNode) {
        InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invoke;
        ExceptionObjectNode exceptionEdge = (ExceptionObjectNode) invokeWithExceptionNode.exceptionEdge();
        exceptionEdge.replaceAtUsages(exceptionObjectPhi);
        exceptionEdge.setNext(null);
        GraphUtil.killCFG(invokeWithExceptionNode.exceptionEdge());
    }
    assert invoke.asNode().isAlive();
    // replace the invoke with a switch on the type of the actual receiver
    boolean methodDispatch = createDispatchOnTypeBeforeInvoke(graph, successors, false, providers.getStampProvider(), providers.getConstantReflection());
    assert invoke.next() == continuation;
    invoke.setNext(null);
    returnMerge.setNext(continuation);
    if (returnValuePhi != null) {
        invoke.asNode().replaceAtUsages(returnValuePhi);
    }
    invoke.asNode().safeDelete();
    ArrayList<PiNode> replacementNodes = new ArrayList<>();
    // prepare the anchors for the invokes
    for (int i = 0; i < numberOfMethods; i++) {
        AbstractBeginNode node = successors[i];
        Invoke invokeForInlining = (Invoke) node.next();
        ResolvedJavaType commonType;
        if (methodDispatch) {
            commonType = concretes.get(i).getDeclaringClass();
        } else {
            commonType = getLeastCommonType(i);
        }
        ValueNode receiver = ((MethodCallTargetNode) invokeForInlining.callTarget()).receiver();
        boolean exact = (getTypeCount(i) == 1 && !methodDispatch);
        PiNode anchoredReceiver = InliningUtil.createAnchoredReceiver(graph, node, commonType, receiver, exact);
        invokeForInlining.callTarget().replaceFirstInput(receiver, anchoredReceiver);
        assert !anchoredReceiver.isDeleted() : anchoredReceiver;
        replacementNodes.add(anchoredReceiver);
    }
    if (shouldFallbackToInvoke()) {
        replacementNodes.add(null);
    }
    EconomicSet<Node> canonicalizeNodes = EconomicSet.create(Equivalence.DEFAULT);
    // do the actual inlining for every invoke
    for (int i = 0; i < numberOfMethods; i++) {
        Invoke invokeForInlining = (Invoke) successors[i].next();
        canonicalizeNodes.addAll(doInline(i, invokeForInlining));
    }
    if (returnValuePhi != null) {
        canonicalizeNodes.add(returnValuePhi);
    }
    return canonicalizeNodes;
}
Also used : ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) InvokeWithExceptionNode(org.graalvm.compiler.nodes.InvokeWithExceptionNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) LoadHubNode(org.graalvm.compiler.nodes.extended.LoadHubNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) DeoptimizeNode(org.graalvm.compiler.nodes.DeoptimizeNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) PiNode(org.graalvm.compiler.nodes.PiNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) TypeSwitchNode(org.graalvm.compiler.nodes.java.TypeSwitchNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) ArrayList(java.util.ArrayList) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) PiNode(org.graalvm.compiler.nodes.PiNode) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) Invoke(org.graalvm.compiler.nodes.Invoke) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) InvokeWithExceptionNode(org.graalvm.compiler.nodes.InvokeWithExceptionNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) DeoptimizeNode(org.graalvm.compiler.nodes.DeoptimizeNode) JavaKind(jdk.vm.ci.meta.JavaKind)

Example 9 with AbstractBeginNode

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

the class SimpleCFGTest method testImplies.

@Test
public void testImplies() {
    OptionValues options = getInitialOptions();
    DebugContext debug = DebugContext.create(options, new GraalDebugHandlersFactory(getSnippetReflection()));
    StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).build();
    EndNode trueEnd = graph.add(new EndNode());
    EndNode falseEnd = graph.add(new EndNode());
    AbstractBeginNode trueBegin = graph.add(new BeginNode());
    trueBegin.setNext(trueEnd);
    AbstractBeginNode falseBegin = graph.add(new BeginNode());
    falseBegin.setNext(falseEnd);
    IfNode ifNode = graph.add(new IfNode(null, trueBegin, falseBegin, 0.5));
    graph.start().setNext(ifNode);
    AbstractMergeNode merge = graph.add(new MergeNode());
    merge.addForwardEnd(trueEnd);
    merge.addForwardEnd(falseEnd);
    ReturnNode returnNode = graph.add(new ReturnNode(null));
    merge.setNext(returnNode);
    dumpGraph(graph);
    ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
    Block[] blocks = cfg.getBlocks();
    // check number of blocks
    assertDeepEquals(4, blocks.length);
    // check block - node assignment
    assertDeepEquals(blocks[0], cfg.blockFor(graph.start()));
    assertDeepEquals(blocks[0], cfg.blockFor(ifNode));
    assertDeepEquals(blocks[1], cfg.blockFor(trueBegin));
    assertDeepEquals(blocks[1], cfg.blockFor(trueEnd));
    assertDeepEquals(blocks[2], cfg.blockFor(falseBegin));
    assertDeepEquals(blocks[2], cfg.blockFor(falseEnd));
    assertDeepEquals(blocks[3], cfg.blockFor(merge));
    assertDeepEquals(blocks[3], cfg.blockFor(returnNode));
    // check dominators
    assertDominator(blocks[0], null);
    assertDominator(blocks[1], blocks[0]);
    assertDominator(blocks[2], blocks[0]);
    assertDominator(blocks[3], blocks[0]);
    // check dominated
    assertDominatedSize(blocks[0], 3);
    assertDominatedSize(blocks[1], 0);
    assertDominatedSize(blocks[2], 0);
    assertDominatedSize(blocks[3], 0);
    // check postdominators
    assertPostdominator(blocks[0], blocks[3]);
    assertPostdominator(blocks[1], blocks[3]);
    assertPostdominator(blocks[2], blocks[3]);
    assertPostdominator(blocks[3], null);
}
Also used : OptionValues(org.graalvm.compiler.options.OptionValues) DebugContext(org.graalvm.compiler.debug.DebugContext) IfNode(org.graalvm.compiler.nodes.IfNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) GraalDebugHandlersFactory(org.graalvm.compiler.printer.GraalDebugHandlersFactory) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) ReturnNode(org.graalvm.compiler.nodes.ReturnNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) EndNode(org.graalvm.compiler.nodes.EndNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) ControlFlowGraph(org.graalvm.compiler.nodes.cfg.ControlFlowGraph) Block(org.graalvm.compiler.nodes.cfg.Block) Test(org.junit.Test)

Example 10 with AbstractBeginNode

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

the class BytecodeParser method emitExplicitBoundsCheck.

protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) {
    AbstractBeginNode trueSucc = graph.add(new BeginNode());
    BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index));
    append(new IfNode(genUnique(IntegerBelowNode.create(constantReflection, metaAccess, options, null, index, length, NodeView.DEFAULT)), trueSucc, exception, FAST_PATH_PROBABILITY));
    lastInstr = trueSucc;
    exception.setStateAfter(createFrameState(bci(), exception));
    exception.setNext(handleException(exception, bci(), false));
}
Also used : BeginNode(org.graalvm.compiler.nodes.BeginNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) KillingBeginNode(org.graalvm.compiler.nodes.KillingBeginNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) BytecodeExceptionNode(org.graalvm.compiler.nodes.extended.BytecodeExceptionNode) IfNode(org.graalvm.compiler.nodes.IfNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Aggregations

AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)63 FixedNode (org.graalvm.compiler.nodes.FixedNode)32 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)31 Node (org.graalvm.compiler.graph.Node)24 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)23 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)23 EndNode (org.graalvm.compiler.nodes.EndNode)22 BeginNode (org.graalvm.compiler.nodes.BeginNode)21 ValueNode (org.graalvm.compiler.nodes.ValueNode)20 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)16 IfNode (org.graalvm.compiler.nodes.IfNode)16 ControlSplitNode (org.graalvm.compiler.nodes.ControlSplitNode)15 MergeNode (org.graalvm.compiler.nodes.MergeNode)15 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)15 LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)14 PhiNode (org.graalvm.compiler.nodes.PhiNode)14 LoopEndNode (org.graalvm.compiler.nodes.LoopEndNode)13 LogicNode (org.graalvm.compiler.nodes.LogicNode)12 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)11 DeoptimizeNode (org.graalvm.compiler.nodes.DeoptimizeNode)11