Search in sources :

Example 36 with FrameState

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

the class CInterfaceEnumTool method invokeEnumLookup.

private InvokeNode invokeEnumLookup(GraphBuilderTool b, CallTargetFactory callTargetFactory, FrameStateBuilder frameState, int bci, EnumInfo enumInfo, JavaKind parameterKind, ValueNode arg) {
    ValueNode[] args = new ValueNode[2];
    args[0] = ConstantNode.forConstant(snippetReflection.forObject(enumInfo.getRuntimeData()), b.getMetaAccess(), b.getGraph());
    assert !Modifier.isStatic(convertCToJavaMethod.getModifiers()) && convertCToJavaMethod.getSignature().getParameterCount(false) == 1;
    JavaKind expectedKind = convertCToJavaMethod.getSignature().getParameterType(0, null).getJavaKind();
    args[1] = CInterfaceInvocationPlugin.adaptPrimitiveType(b.getGraph(), arg, parameterKind, expectedKind, false);
    ResolvedJavaType convertReturnType = (ResolvedJavaType) convertCToJavaMethod.getSignature().getReturnType(null);
    StampPair returnStamp = StampFactory.forDeclaredType(null, convertReturnType, false);
    MethodCallTargetNode callTargetNode = b.append(callTargetFactory.createMethodCallTarget(InvokeKind.Virtual, convertCToJavaMethod, args, returnStamp, bci));
    Stamp invokeStamp = StampFactory.object(TypeReference.createWithoutAssumptions(convertReturnType));
    InvokeNode invoke = b.append(new InvokeNode(callTargetNode, bci, invokeStamp));
    frameState.push(convertReturnType.getJavaKind(), invoke);
    FrameState stateWithInvoke = frameState.create(bci, invoke);
    frameState.pop(convertReturnType.getJavaKind());
    invoke.setStateAfter(stateWithInvoke);
    return invoke;
}
Also used : MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) ObjectStamp(org.graalvm.compiler.core.common.type.ObjectStamp) Stamp(org.graalvm.compiler.core.common.type.Stamp) ValueNode(org.graalvm.compiler.nodes.ValueNode) StampPair(org.graalvm.compiler.core.common.type.StampPair) InvokeNode(org.graalvm.compiler.nodes.InvokeNode) FrameState(org.graalvm.compiler.nodes.FrameState) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) JavaKind(jdk.vm.ci.meta.JavaKind)

Example 37 with FrameState

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

the class HostedBytecodeParser method finishInstruction.

/**
 * Insert deopt entries after all state splits.
 */
@Override
protected FixedWithNextNode finishInstruction(FixedWithNextNode instr, FrameStateBuilder stateBuilder) {
    if (getMethod().compilationInfo.isDeoptTarget() && !parsingIntrinsic()) {
        FrameState stateAfter = null;
        if (instr instanceof StateSplit && !(instr instanceof DeoptEntryNode)) {
            /*
                 * The regular case: the instruction is a state split and we insert a DeoptEntryNode
                 * right after it.
                 */
            StateSplit stateSplit = (StateSplit) instr;
            stateAfter = stateSplit.stateAfter();
        } else if (instr instanceof AbstractBeginNode) {
            /*
                 * We are at a block begin. If the block predecessor is a LoopExitNode or an
                 * InvokeWithException (both are state splits), we didn't inserted a deopt entry
                 * yet. So we do it at the begin of a block.
                 *
                 * Note that this only happens if the LoopExitNode/InvokeWithException is the
                 * _single_ predcessor of this block. In case of multiple predecessors, the block
                 * starts with a MergeNode and this is handled like a regular case.
                 */
            Node predecessor = instr.predecessor();
            if (predecessor instanceof KillingBeginNode) {
                /*
                     * This is between an InvokeWithException and the BlockPlaceholderNode.
                     */
                predecessor = predecessor.predecessor();
            }
            if (predecessor instanceof StateSplit && !(predecessor instanceof DeoptEntryNode)) {
                stateAfter = ((StateSplit) predecessor).stateAfter();
            }
        }
        boolean needsDeoptEntry = false;
        boolean needsProxies = false;
        if (stateAfter != null) {
            if (getMethod().compilationInfo.isDeoptEntry(stateAfter.bci, stateAfter.duringCall(), stateAfter.rethrowException())) {
                needsDeoptEntry = true;
                needsProxies = true;
            } else if (instr.predecessor() instanceof Invoke && getMethod().compilationInfo.isDeoptEntry(((Invoke) instr.predecessor()).bci(), true, false)) {
                /*
                     * Invoke nodes can be implicit deoptimization entry points. But we cannot
                     * anchor proxy nodes on invocations: The invoke has two successors (normal and
                     * exception handler), and we need to proxy values at the beginning of both.
                     */
                needsProxies = true;
            } else if (instr instanceof ExceptionObjectNode && getMethod().compilationInfo.isDeoptEntry(((ExceptionObjectNode) instr).stateAfter().bci, true, false)) {
                /*
                     * The predecessor of the ExceptionObjectNode will be an Invoke, but the Invoke
                     * has not been created yet. So the check above for the predecessor does not
                     * trigger.
                     */
                needsProxies = true;
            }
        }
        if (needsProxies) {
            long encodedBci = FrameInfoEncoder.encodeBci(stateAfter.bci, stateAfter.duringCall(), stateAfter.rethrowException());
            DeoptProxyAnchorNode existingDeoptEntry = deoptEntries.get(encodedBci);
            if (existingDeoptEntry != STICKY_DEOPT_ENTRY) {
                if (existingDeoptEntry != null) {
                    /*
                         * Some state splits (i.e. MergeNode and DispatchBeginNode) do not have a
                         * correspondent byte code. Therefore there can be a previously added deopt
                         * entry with the same BCI. For MergeNodes we replace the previous entry
                         * because the new frame state has less live locals.
                         */
                    existingDeoptEntry.replaceAtUsages(null);
                    graph.removeFixed(existingDeoptEntry);
                    deoptEntries.remove(encodedBci);
                    if (existingDeoptEntry instanceof DeoptEntryNode) {
                        /*
                             * We already had a DeoptEntryNode registered earlier for some reason,
                             * so be conservative and create one again (and not just a
                             * DeoptProxyAnchorNode).
                             */
                        needsDeoptEntry = true;
                    }
                }
                assert !deoptEntries.containsKey(encodedBci) : "duplicate deopt entry for encoded BCI " + encodedBci;
                DeoptProxyAnchorNode deoptEntry = createDeoptEntry(stateBuilder, stateAfter, !needsDeoptEntry);
                if (instr instanceof LoopBeginNode) {
                    /*
                         * Loop headers to not have their own bci. Never move a deopt entry for the
                         * loop header down, e.g., into a loop end (that might then end up to be
                         * dead code).
                         */
                    deoptEntries.put(encodedBci, STICKY_DEOPT_ENTRY);
                } else {
                    deoptEntries.put(encodedBci, deoptEntry);
                }
                assert instr.next() == null : "cannot append instruction to instruction which isn't end (" + instr + "->" + instr.next() + ")";
                instr.setNext(deoptEntry);
                return deoptEntry;
            }
        }
    }
    return super.finishInstruction(instr, stateBuilder);
}
Also used : DeoptProxyAnchorNode(com.oracle.svm.core.graal.nodes.DeoptProxyAnchorNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) DeoptEntryNode(com.oracle.svm.core.graal.nodes.DeoptEntryNode) KillingBeginNode(org.graalvm.compiler.nodes.KillingBeginNode) SubstrateMethodCallTargetNode(com.oracle.svm.hosted.nodes.SubstrateMethodCallTargetNode) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) DeoptEntryNode(com.oracle.svm.core.graal.nodes.DeoptEntryNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) DeoptProxyAnchorNode(com.oracle.svm.core.graal.nodes.DeoptProxyAnchorNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Node(org.graalvm.compiler.graph.Node) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) DeoptProxyNode(com.oracle.svm.hosted.nodes.DeoptProxyNode) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) KillingBeginNode(org.graalvm.compiler.nodes.KillingBeginNode) FrameState(org.graalvm.compiler.nodes.FrameState) StateSplit(org.graalvm.compiler.nodes.StateSplit) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) Invoke(org.graalvm.compiler.nodes.Invoke)

Example 38 with FrameState

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

the class LoopFragment method mergeEarlyExits.

/**
 * Merges the early exits (i.e. loop exits) that were duplicated as part of this fragment, with
 * the original fragment's exits.
 */
protected void mergeEarlyExits() {
    assert isDuplicate();
    StructuredGraph graph = graph();
    for (AbstractBeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().loop().getExits())) {
        LoopExitNode loopEarlyExit = (LoopExitNode) earlyExit;
        FixedNode next = loopEarlyExit.next();
        if (loopEarlyExit.isDeleted() || !this.original().contains(loopEarlyExit)) {
            continue;
        }
        AbstractBeginNode newEarlyExit = getDuplicatedNode(loopEarlyExit);
        if (newEarlyExit == null) {
            continue;
        }
        MergeNode merge = graph.add(new MergeNode());
        EndNode originalEnd = graph.add(new EndNode());
        EndNode newEnd = graph.add(new EndNode());
        merge.addForwardEnd(originalEnd);
        merge.addForwardEnd(newEnd);
        loopEarlyExit.setNext(originalEnd);
        newEarlyExit.setNext(newEnd);
        merge.setNext(next);
        FrameState exitState = loopEarlyExit.stateAfter();
        if (exitState != null) {
            FrameState originalExitState = exitState;
            exitState = exitState.duplicateWithVirtualState();
            loopEarlyExit.setStateAfter(exitState);
            merge.setStateAfter(originalExitState);
            /*
                 * Using the old exit's state as the merge's state is necessary because some of the
                 * VirtualState nodes contained in the old exit's state may be shared by other
                 * dominated VirtualStates. Those dominated virtual states need to see the
                 * proxy->phi update that are applied below.
                 *
                 * We now update the original fragment's nodes accordingly:
                 */
            originalExitState.applyToVirtual(node -> original.nodes.clearAndGrow(node));
            exitState.applyToVirtual(node -> original.nodes.markAndGrow(node));
        }
        FrameState finalExitState = exitState;
        for (Node anchored : loopEarlyExit.anchored().snapshot()) {
            anchored.replaceFirstInput(loopEarlyExit, merge);
        }
        boolean newEarlyExitIsLoopExit = newEarlyExit instanceof LoopExitNode;
        for (ProxyNode vpn : loopEarlyExit.proxies().snapshot()) {
            if (vpn.hasNoUsages()) {
                continue;
            }
            if (vpn.value() == null) {
                assert vpn instanceof GuardProxyNode;
                vpn.replaceAtUsages(null);
                continue;
            }
            final ValueNode replaceWith;
            ValueNode newVpn = prim(newEarlyExitIsLoopExit ? vpn : vpn.value());
            if (newVpn != null) {
                PhiNode phi;
                if (vpn instanceof ValueProxyNode) {
                    phi = graph.addWithoutUnique(new ValuePhiNode(vpn.stamp(NodeView.DEFAULT), merge));
                } else if (vpn instanceof GuardProxyNode) {
                    phi = graph.addWithoutUnique(new GuardPhiNode(merge));
                } else {
                    throw GraalError.shouldNotReachHere();
                }
                phi.addInput(vpn);
                phi.addInput(newVpn);
                replaceWith = phi;
            } else {
                replaceWith = vpn.value();
            }
            vpn.replaceAtMatchingUsages(replaceWith, usage -> {
                if (merge.isPhiAtMerge(usage)) {
                    return false;
                }
                if (usage instanceof VirtualState) {
                    VirtualState stateUsage = (VirtualState) usage;
                    if (finalExitState != null && finalExitState.isPartOfThisState(stateUsage)) {
                        return false;
                    }
                }
                return true;
            });
        }
    }
}
Also used : GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) GuardNode(org.graalvm.compiler.nodes.GuardNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) CommitAllocationNode(org.graalvm.compiler.nodes.virtual.CommitAllocationNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) MonitorEnterNode(org.graalvm.compiler.nodes.java.MonitorEnterNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) FrameState(org.graalvm.compiler.nodes.FrameState) VirtualState(org.graalvm.compiler.nodes.VirtualState) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) EndNode(org.graalvm.compiler.nodes.EndNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) ValueNode(org.graalvm.compiler.nodes.ValueNode)

Example 39 with FrameState

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

the class LoopFragment method computeNodes.

protected static void computeNodes(NodeBitMap nodes, Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) {
    for (AbstractBeginNode b : blocks) {
        if (b.isDeleted()) {
            continue;
        }
        for (Node n : b.getBlockNodes()) {
            if (n instanceof Invoke) {
                nodes.mark(((Invoke) n).callTarget());
            }
            if (n instanceof NodeWithState) {
                NodeWithState withState = (NodeWithState) n;
                withState.states().forEach(state -> state.applyToVirtual(node -> nodes.mark(node)));
            }
            if (n instanceof AbstractMergeNode) {
                // if a merge is in the loop, all of its phis are also in the loop
                for (PhiNode phi : ((AbstractMergeNode) n).phis()) {
                    nodes.mark(phi);
                }
            }
            nodes.mark(n);
        }
    }
    for (AbstractBeginNode earlyExit : earlyExits) {
        if (earlyExit.isDeleted()) {
            continue;
        }
        nodes.mark(earlyExit);
        if (earlyExit instanceof LoopExitNode) {
            LoopExitNode loopExit = (LoopExitNode) earlyExit;
            FrameState stateAfter = loopExit.stateAfter();
            if (stateAfter != null) {
                stateAfter.applyToVirtual(node -> nodes.mark(node));
            }
            for (ProxyNode proxy : loopExit.proxies()) {
                nodes.mark(proxy);
            }
        }
    }
    final NodeBitMap nonLoopNodes = graph.createNodeBitMap();
    Deque<WorkListEntry> worklist = new ArrayDeque<>();
    for (AbstractBeginNode b : blocks) {
        if (b.isDeleted()) {
            continue;
        }
        for (Node n : b.getBlockNodes()) {
            if (n instanceof CommitAllocationNode) {
                for (VirtualObjectNode obj : ((CommitAllocationNode) n).getVirtualObjects()) {
                    markFloating(worklist, obj, nodes, nonLoopNodes);
                }
            }
            if (n instanceof MonitorEnterNode) {
                markFloating(worklist, ((MonitorEnterNode) n).getMonitorId(), nodes, nonLoopNodes);
            }
            if (n instanceof AbstractMergeNode) {
                /*
                     * Since we already marked all phi nodes as being in the loop to break cycles,
                     * we also have to iterate over their usages here.
                     */
                for (PhiNode phi : ((AbstractMergeNode) n).phis()) {
                    for (Node usage : phi.usages()) {
                        markFloating(worklist, usage, nodes, nonLoopNodes);
                    }
                }
            }
            for (Node usage : n.usages()) {
                markFloating(worklist, usage, nodes, nonLoopNodes);
            }
        }
    }
}
Also used : GuardNode(org.graalvm.compiler.nodes.GuardNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) Deque(java.util.Deque) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) TriState(jdk.vm.ci.meta.TriState) EconomicMap(org.graalvm.collections.EconomicMap) MergeNode(org.graalvm.compiler.nodes.MergeNode) VirtualState(org.graalvm.compiler.nodes.VirtualState) FixedNode(org.graalvm.compiler.nodes.FixedNode) NodeWithState(org.graalvm.compiler.nodes.spi.NodeWithState) Iterator(java.util.Iterator) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) NodeView(org.graalvm.compiler.nodes.NodeView) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) CommitAllocationNode(org.graalvm.compiler.nodes.virtual.CommitAllocationNode) Graph(org.graalvm.compiler.graph.Graph) ValueNode(org.graalvm.compiler.nodes.ValueNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) DuplicationReplacement(org.graalvm.compiler.graph.Graph.DuplicationReplacement) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) FrameState(org.graalvm.compiler.nodes.FrameState) NodeIterable(org.graalvm.compiler.graph.iterators.NodeIterable) Invoke(org.graalvm.compiler.nodes.Invoke) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) MonitorEnterNode(org.graalvm.compiler.nodes.java.MonitorEnterNode) Block(org.graalvm.compiler.nodes.cfg.Block) GraalError(org.graalvm.compiler.debug.GraalError) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) ArrayDeque(java.util.ArrayDeque) Collections(java.util.Collections) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) GuardNode(org.graalvm.compiler.nodes.GuardNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) CommitAllocationNode(org.graalvm.compiler.nodes.virtual.CommitAllocationNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) MonitorEnterNode(org.graalvm.compiler.nodes.java.MonitorEnterNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) FrameState(org.graalvm.compiler.nodes.FrameState) ArrayDeque(java.util.ArrayDeque) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) Invoke(org.graalvm.compiler.nodes.Invoke) MonitorEnterNode(org.graalvm.compiler.nodes.java.MonitorEnterNode) NodeWithState(org.graalvm.compiler.nodes.spi.NodeWithState) CommitAllocationNode(org.graalvm.compiler.nodes.virtual.CommitAllocationNode)

Example 40 with FrameState

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

the class LoopFragmentInside method mergeEnds.

private AbstractBeginNode mergeEnds() {
    assert isDuplicate();
    List<EndNode> endsToMerge = new LinkedList<>();
    // map peel exits to the corresponding loop exits
    EconomicMap<AbstractEndNode, LoopEndNode> reverseEnds = EconomicMap.create(Equivalence.IDENTITY);
    LoopBeginNode loopBegin = original().loop().loopBegin();
    for (LoopEndNode le : loopBegin.loopEnds()) {
        AbstractEndNode duplicate = getDuplicatedNode(le);
        if (duplicate != null) {
            endsToMerge.add((EndNode) duplicate);
            reverseEnds.put(duplicate, le);
        }
    }
    mergedInitializers = EconomicMap.create(Equivalence.IDENTITY);
    AbstractBeginNode newExit;
    StructuredGraph graph = graph();
    if (endsToMerge.size() == 1) {
        AbstractEndNode end = endsToMerge.get(0);
        assert end.hasNoUsages();
        newExit = graph.add(new BeginNode());
        end.replaceAtPredecessor(newExit);
        end.safeDelete();
    } else {
        assert endsToMerge.size() > 1;
        AbstractMergeNode newExitMerge = graph.add(new MergeNode());
        newExit = newExitMerge;
        FrameState state = loopBegin.stateAfter();
        FrameState duplicateState = null;
        if (state != null) {
            duplicateState = state.duplicateWithVirtualState();
            newExitMerge.setStateAfter(duplicateState);
        }
        for (EndNode end : endsToMerge) {
            newExitMerge.addForwardEnd(end);
        }
        for (final PhiNode phi : loopBegin.phis().snapshot()) {
            if (phi.hasNoUsages()) {
                continue;
            }
            final PhiNode firstPhi = patchPhi(graph, phi, newExitMerge);
            for (AbstractEndNode end : newExitMerge.forwardEnds()) {
                LoopEndNode loopEnd = reverseEnds.get(end);
                ValueNode prim = prim(phi.valueAt(loopEnd));
                assert prim != null;
                firstPhi.addInput(prim);
            }
            ValueNode initializer = firstPhi;
            if (duplicateState != null) {
                // fix the merge's state after
                duplicateState.applyToNonVirtual(new NodeClosure<ValueNode>() {

                    @Override
                    public void apply(Node from, ValueNode node) {
                        if (node == phi) {
                            from.replaceFirstInput(phi, firstPhi);
                        }
                    }
                });
            }
            mergedInitializers.put(phi, initializer);
        }
    }
    return newExit;
}
Also used : ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) CompareNode(org.graalvm.compiler.nodes.calc.CompareNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) AddNode(org.graalvm.compiler.nodes.calc.AddNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) IfNode(org.graalvm.compiler.nodes.IfNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) SubNode(org.graalvm.compiler.nodes.calc.SubNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) SafepointNode(org.graalvm.compiler.nodes.SafepointNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) FrameState(org.graalvm.compiler.nodes.FrameState) LinkedList(java.util.LinkedList) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) EndNode(org.graalvm.compiler.nodes.EndNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) BeginNode(org.graalvm.compiler.nodes.BeginNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) ValueNode(org.graalvm.compiler.nodes.ValueNode)

Aggregations

FrameState (org.graalvm.compiler.nodes.FrameState)73 ValueNode (org.graalvm.compiler.nodes.ValueNode)38 Node (org.graalvm.compiler.graph.Node)27 FixedNode (org.graalvm.compiler.nodes.FixedNode)21 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)19 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)19 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)16 ParameterNode (org.graalvm.compiler.nodes.ParameterNode)16 PhiNode (org.graalvm.compiler.nodes.PhiNode)16 EndNode (org.graalvm.compiler.nodes.EndNode)15 MethodCallTargetNode (org.graalvm.compiler.nodes.java.MethodCallTargetNode)15 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)14 MergeNode (org.graalvm.compiler.nodes.MergeNode)14 ReturnNode (org.graalvm.compiler.nodes.ReturnNode)13 InvokeWithExceptionNode (org.graalvm.compiler.nodes.InvokeWithExceptionNode)12 StateSplit (org.graalvm.compiler.nodes.StateSplit)12 MonitorIdNode (org.graalvm.compiler.nodes.java.MonitorIdNode)12 DebugContext (org.graalvm.compiler.debug.DebugContext)11 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)11 DeoptimizeNode (org.graalvm.compiler.nodes.DeoptimizeNode)11