Search in sources :

Example 66 with Node

use of org.graalvm.compiler.graph.Node in project graal by oracle.

the class GraphOrder method assertSchedulableGraph.

/**
 * This method schedules the graph and makes sure that, for every node, all inputs are available
 * at the position where it is scheduled. This is a very expensive assertion.
 */
public static boolean assertSchedulableGraph(final StructuredGraph graph) {
    assert graph.getGuardsStage() != GuardsStage.AFTER_FSA : "Cannot use the BlockIteratorClosure after FrameState Assignment, HIR Loop Data Structures are no longer valid.";
    try {
        final SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true);
        final EconomicMap<LoopBeginNode, NodeBitMap> loopEntryStates = EconomicMap.create(Equivalence.IDENTITY);
        schedulePhase.apply(graph, false);
        final ScheduleResult schedule = graph.getLastSchedule();
        BlockIteratorClosure<NodeBitMap> closure = new BlockIteratorClosure<NodeBitMap>() {

            @Override
            protected List<NodeBitMap> processLoop(Loop<Block> loop, NodeBitMap initialState) {
                return ReentrantBlockIterator.processLoop(this, loop, initialState).exitStates;
            }

            @Override
            protected NodeBitMap processBlock(final Block block, final NodeBitMap currentState) {
                final List<Node> list = graph.getLastSchedule().getBlockToNodesMap().get(block);
                /*
                     * A stateAfter is not valid directly after its associated state split, but
                     * right before the next fixed node. Therefore a pending stateAfter is kept that
                     * will be checked at the correct position.
                     */
                FrameState pendingStateAfter = null;
                for (final Node node : list) {
                    if (node instanceof ValueNode) {
                        FrameState stateAfter = node instanceof StateSplit ? ((StateSplit) node).stateAfter() : null;
                        if (node instanceof FullInfopointNode) {
                            stateAfter = ((FullInfopointNode) node).getState();
                        }
                        if (pendingStateAfter != null && node instanceof FixedNode) {
                            pendingStateAfter.applyToNonVirtual(new NodeClosure<Node>() {

                                @Override
                                public void apply(Node usage, Node nonVirtualNode) {
                                    assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode || nonVirtualNode instanceof ConstantNode : nonVirtualNode + " not available at virtualstate " + usage + " before " + node + " in block " + block + " \n" + list;
                                }
                            });
                            pendingStateAfter = null;
                        }
                        if (node instanceof AbstractMergeNode) {
                            // phis aren't scheduled, so they need to be added explicitly
                            currentState.markAll(((AbstractMergeNode) node).phis());
                            if (node instanceof LoopBeginNode) {
                                // remember the state at the loop entry, it's restored at exits
                                loopEntryStates.put((LoopBeginNode) node, currentState.copy());
                            }
                        } else if (node instanceof ProxyNode) {
                            assert false : "proxy nodes should not be in the schedule";
                        } else if (node instanceof LoopExitNode) {
                            if (graph.hasValueProxies()) {
                                for (ProxyNode proxy : ((LoopExitNode) node).proxies()) {
                                    for (Node input : proxy.inputs()) {
                                        if (input != proxy.proxyPoint()) {
                                            assert currentState.isMarked(input) : input + " not available at " + proxy + " in block " + block + "\n" + list;
                                        }
                                    }
                                }
                                // loop contents are only accessible via proxies at the exit
                                currentState.clearAll();
                                currentState.markAll(loopEntryStates.get(((LoopExitNode) node).loopBegin()));
                            }
                            // Loop proxies aren't scheduled, so they need to be added
                            // explicitly
                            currentState.markAll(((LoopExitNode) node).proxies());
                        } else {
                            for (Node input : node.inputs()) {
                                if (input != stateAfter) {
                                    if (input instanceof FrameState) {
                                        ((FrameState) input).applyToNonVirtual(new VirtualState.NodeClosure<Node>() {

                                            @Override
                                            public void apply(Node usage, Node nonVirtual) {
                                                assert currentState.isMarked(nonVirtual) : nonVirtual + " not available at " + node + " in block " + block + "\n" + list;
                                            }
                                        });
                                    } else {
                                        assert currentState.isMarked(input) || input instanceof VirtualObjectNode || input instanceof ConstantNode : input + " not available at " + node + " in block " + block + "\n" + list;
                                    }
                                }
                            }
                        }
                        if (node instanceof AbstractEndNode) {
                            AbstractMergeNode merge = ((AbstractEndNode) node).merge();
                            for (PhiNode phi : merge.phis()) {
                                ValueNode phiValue = phi.valueAt((AbstractEndNode) node);
                                assert phiValue == null || currentState.isMarked(phiValue) || phiValue instanceof ConstantNode : phiValue + " not available at phi " + phi + " / end " + node + " in block " + block;
                            }
                        }
                        if (stateAfter != null) {
                            assert pendingStateAfter == null;
                            pendingStateAfter = stateAfter;
                        }
                        currentState.mark(node);
                    }
                }
                if (pendingStateAfter != null) {
                    pendingStateAfter.applyToNonVirtual(new NodeClosure<Node>() {

                        @Override
                        public void apply(Node usage, Node nonVirtualNode) {
                            assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode || nonVirtualNode instanceof ConstantNode : nonVirtualNode + " not available at virtualstate " + usage + " at end of block " + block + " \n" + list;
                        }
                    });
                }
                return currentState;
            }

            @Override
            protected NodeBitMap merge(Block merge, List<NodeBitMap> states) {
                NodeBitMap result = states.get(0);
                for (int i = 1; i < states.size(); i++) {
                    result.intersect(states.get(i));
                }
                return result;
            }

            @Override
            protected NodeBitMap getInitialState() {
                NodeBitMap ret = graph.createNodeBitMap();
                ret.markAll(graph.getNodes().filter(ConstantNode.class));
                return ret;
            }

            @Override
            protected NodeBitMap cloneState(NodeBitMap oldState) {
                return oldState.copy();
            }
        };
        ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
    } catch (Throwable t) {
        graph.getDebug().handle(t);
    }
    return true;
}
Also used : VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) SchedulePhase(org.graalvm.compiler.phases.schedule.SchedulePhase) ScheduleResult(org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) FullInfopointNode(org.graalvm.compiler.nodes.FullInfopointNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) FrameState(org.graalvm.compiler.nodes.FrameState) VirtualState(org.graalvm.compiler.nodes.VirtualState) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) ArrayList(java.util.ArrayList) List(java.util.List) Loop(org.graalvm.compiler.core.common.cfg.Loop) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) BlockIteratorClosure(org.graalvm.compiler.phases.graph.ReentrantBlockIterator.BlockIteratorClosure) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) FullInfopointNode(org.graalvm.compiler.nodes.FullInfopointNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Block(org.graalvm.compiler.nodes.cfg.Block) StateSplit(org.graalvm.compiler.nodes.StateSplit)

Example 67 with Node

use of org.graalvm.compiler.graph.Node in project graal by oracle.

the class GraphOrder method assertNonCyclicGraph.

/**
 * Quick (and imprecise) assertion that there are no (invalid) cycles in the given graph. First,
 * an ordered list of all nodes in the graph (a total ordering) is created. A second run over
 * this list checks whether inputs are scheduled before their usages.
 *
 * @param graph the graph to be checked.
 * @throws AssertionError if a cycle was detected.
 */
public static boolean assertNonCyclicGraph(StructuredGraph graph) {
    List<Node> order = createOrder(graph);
    NodeBitMap visited = graph.createNodeBitMap();
    visited.clearAll();
    for (Node node : order) {
        if (node instanceof PhiNode && ((PhiNode) node).merge() instanceof LoopBeginNode) {
            assert visited.isMarked(((PhiNode) node).valueAt(0));
        // nothing to do
        } else {
            for (Node input : node.inputs()) {
                if (!visited.isMarked(input)) {
                    if (input instanceof FrameState) {
                    // nothing to do - frame states are known, allowed cycles
                    } else {
                        assert false : "unexpected cycle detected at input " + node + " -> " + input;
                    }
                }
            }
        }
        visited.mark(node);
    }
    return true;
}
Also used : LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) FullInfopointNode(org.graalvm.compiler.nodes.FullInfopointNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) FrameState(org.graalvm.compiler.nodes.FrameState)

Example 68 with Node

use of org.graalvm.compiler.graph.Node in project graal by oracle.

the class VerifyDebugUsage method verifyParameters.

private void verifyParameters(MethodCallTargetNode callTarget, StructuredGraph callerGraph, NodeInputList<? extends ValueNode> args, ResolvedJavaType stringType, int startArgIdx) {
    if (callTarget.targetMethod().isVarArgs() && args.get(args.count() - 1) instanceof NewArrayNode) {
        // unpack the arguments to the var args
        List<ValueNode> unpacked = new ArrayList<>(args.snapshot());
        NewArrayNode varArgParameter = (NewArrayNode) unpacked.remove(unpacked.size() - 1);
        int firstVarArg = unpacked.size();
        for (Node usage : varArgParameter.usages()) {
            if (usage instanceof StoreIndexedNode) {
                StoreIndexedNode si = (StoreIndexedNode) usage;
                unpacked.add(si.value());
            }
        }
        verifyParameters(callerGraph, callTarget, unpacked, stringType, startArgIdx, firstVarArg);
    } else {
        verifyParameters(callerGraph, callTarget, args, stringType, startArgIdx, -1);
    }
}
Also used : StoreIndexedNode(org.graalvm.compiler.nodes.java.StoreIndexedNode) NewArrayNode(org.graalvm.compiler.nodes.java.NewArrayNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) CallTargetNode(org.graalvm.compiler.nodes.CallTargetNode) StoreIndexedNode(org.graalvm.compiler.nodes.java.StoreIndexedNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Node(org.graalvm.compiler.graph.Node) NewArrayNode(org.graalvm.compiler.nodes.java.NewArrayNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) ArrayList(java.util.ArrayList)

Example 69 with Node

use of org.graalvm.compiler.graph.Node in project graal by oracle.

the class VerifyGraphAddUsage method verify.

@Override
protected boolean verify(StructuredGraph graph, PhaseContext context) {
    boolean allowed = false;
    for (Class<?> cls : ALLOWED_CLASSES) {
        ResolvedJavaType declaringClass = graph.method().getDeclaringClass();
        if (context.getMetaAccess().lookupJavaType(cls).isAssignableFrom(declaringClass)) {
            allowed = true;
        }
    }
    if (!allowed) {
        ResolvedJavaMethod addOrUniqueMethod = context.getMetaAccess().lookupJavaMethod(ADD_OR_UNIQUE);
        for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) {
            ResolvedJavaMethod callee = t.targetMethod();
            if (callee.equals(addOrUniqueMethod)) {
                ValueNode nodeArgument = t.arguments().get(1);
                EconomicSet<Node> seen = EconomicSet.create();
                checkNonFactory(graph, seen, context, nodeArgument);
            }
        }
    }
    return true;
}
Also used : MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) PiNode(org.graalvm.compiler.nodes.PiNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) Node(org.graalvm.compiler.graph.Node) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) NewInstanceNode(org.graalvm.compiler.nodes.java.NewInstanceNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) ResolvedJavaMethod(jdk.vm.ci.meta.ResolvedJavaMethod)

Example 70 with Node

use of org.graalvm.compiler.graph.Node in project graal by oracle.

the class ReentrantNodeIterator method apply.

private static <StateT> EconomicMap<FixedNode, StateT> apply(NodeIteratorClosure<StateT> closure, FixedNode start, StateT initialState, LoopBeginNode boundary) {
    assert start != null;
    Deque<AbstractBeginNode> nodeQueue = new ArrayDeque<>();
    EconomicMap<FixedNode, StateT> blockEndStates = EconomicMap.create(Equivalence.IDENTITY);
    StateT state = initialState;
    FixedNode current = start;
    do {
        while (current instanceof FixedWithNextNode) {
            if (boundary != null && current instanceof LoopExitNode && ((LoopExitNode) current).loopBegin() == boundary) {
                blockEndStates.put(current, state);
                current = null;
            } else {
                FixedNode next = ((FixedWithNextNode) current).next();
                state = closure.processNode(current, state);
                current = closure.continueIteration(state) ? next : null;
            }
        }
        if (current != null) {
            state = closure.processNode(current, state);
            if (closure.continueIteration(state)) {
                Iterator<Node> successors = current.successors().iterator();
                if (!successors.hasNext()) {
                    if (current instanceof LoopEndNode) {
                        blockEndStates.put(current, state);
                    } else if (current instanceof EndNode) {
                        // add the end node and see if the merge is ready for processing
                        AbstractMergeNode merge = ((EndNode) current).merge();
                        if (merge instanceof LoopBeginNode) {
                            EconomicMap<LoopExitNode, StateT> loopExitState = closure.processLoop((LoopBeginNode) merge, state);
                            MapCursor<LoopExitNode, StateT> entry = loopExitState.getEntries();
                            while (entry.advance()) {
                                blockEndStates.put(entry.getKey(), entry.getValue());
                                nodeQueue.add(entry.getKey());
                            }
                        } else {
                            boolean endsVisited = true;
                            for (AbstractEndNode forwardEnd : merge.forwardEnds()) {
                                if (forwardEnd != current && !blockEndStates.containsKey(forwardEnd)) {
                                    endsVisited = false;
                                    break;
                                }
                            }
                            if (endsVisited) {
                                ArrayList<StateT> states = new ArrayList<>(merge.forwardEndCount());
                                for (int i = 0; i < merge.forwardEndCount(); i++) {
                                    AbstractEndNode forwardEnd = merge.forwardEndAt(i);
                                    assert forwardEnd == current || blockEndStates.containsKey(forwardEnd);
                                    StateT other = forwardEnd == current ? state : blockEndStates.removeKey(forwardEnd);
                                    states.add(other);
                                }
                                state = closure.merge(merge, states);
                                current = closure.continueIteration(state) ? merge : null;
                                continue;
                            } else {
                                assert !blockEndStates.containsKey(current);
                                blockEndStates.put(current, state);
                            }
                        }
                    }
                } else {
                    FixedNode firstSuccessor = (FixedNode) successors.next();
                    if (!successors.hasNext()) {
                        current = firstSuccessor;
                        continue;
                    } else {
                        do {
                            AbstractBeginNode successor = (AbstractBeginNode) successors.next();
                            StateT successorState = closure.afterSplit(successor, state);
                            if (closure.continueIteration(successorState)) {
                                blockEndStates.put(successor, successorState);
                                nodeQueue.add(successor);
                            }
                        } while (successors.hasNext());
                        state = closure.afterSplit((AbstractBeginNode) firstSuccessor, state);
                        current = closure.continueIteration(state) ? firstSuccessor : null;
                        continue;
                    }
                }
            }
        }
        // get next queued block
        if (nodeQueue.isEmpty()) {
            return blockEndStates;
        } else {
            current = nodeQueue.removeFirst();
            assert blockEndStates.containsKey(current);
            state = blockEndStates.removeKey(current);
            assert !(current instanceof AbstractMergeNode) && current instanceof AbstractBeginNode;
        }
    } while (true);
}
Also used : FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) EconomicMap(org.graalvm.collections.EconomicMap) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) ArrayList(java.util.ArrayList) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ArrayDeque(java.util.ArrayDeque) MapCursor(org.graalvm.collections.MapCursor) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) EndNode(org.graalvm.compiler.nodes.EndNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode)

Aggregations

Node (org.graalvm.compiler.graph.Node)189 ValueNode (org.graalvm.compiler.nodes.ValueNode)105 FixedNode (org.graalvm.compiler.nodes.FixedNode)91 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)75 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)74 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)73 PhiNode (org.graalvm.compiler.nodes.PhiNode)64 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)61 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)53 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)47 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)43 FloatingNode (org.graalvm.compiler.nodes.calc.FloatingNode)41 ParameterNode (org.graalvm.compiler.nodes.ParameterNode)38 EndNode (org.graalvm.compiler.nodes.EndNode)37 LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)37 MethodCallTargetNode (org.graalvm.compiler.nodes.java.MethodCallTargetNode)37 MergeNode (org.graalvm.compiler.nodes.MergeNode)35 ReturnNode (org.graalvm.compiler.nodes.ReturnNode)35 VirtualObjectNode (org.graalvm.compiler.nodes.virtual.VirtualObjectNode)32 LogicNode (org.graalvm.compiler.nodes.LogicNode)31