Search in sources :

Example 26 with AbstractMergeNode

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

the class ReentrantBlockIterator method apply.

public static <StateT> EconomicMap<FixedNode, StateT> apply(BlockIteratorClosure<StateT> closure, Block start, StateT initialState, Predicate<Block> stopAtBlock) {
    Deque<Block> blockQueue = new ArrayDeque<>();
    /*
         * States are stored on EndNodes before merges, and on BeginNodes after ControlSplitNodes.
         */
    EconomicMap<FixedNode, StateT> states = EconomicMap.create(Equivalence.IDENTITY);
    StateT state = initialState;
    Block current = start;
    StructuredGraph graph = start.getBeginNode().graph();
    CompilationAlarm compilationAlarm = CompilationAlarm.current();
    while (true) {
        if (compilationAlarm.hasExpired()) {
            int period = CompilationAlarm.Options.CompilationExpirationPeriod.getValue(graph.getOptions());
            if (period > 120) {
                throw new PermanentBailoutException("Compilation exceeded %d seconds during CFG traversal", period);
            } else {
                throw new RetryableBailoutException("Compilation exceeded %d seconds during CFG traversal", period);
            }
        }
        Block next = null;
        if (stopAtBlock != null && stopAtBlock.test(current)) {
            states.put(current.getBeginNode(), state);
        } else {
            state = closure.processBlock(current, state);
            Block[] successors = current.getSuccessors();
            if (successors.length == 0) {
            // nothing to do...
            } else if (successors.length == 1) {
                Block successor = successors[0];
                if (successor.isLoopHeader()) {
                    if (current.isLoopEnd()) {
                        // nothing to do... loop ends only lead to loop begins we've already
                        // visited
                        states.put(current.getEndNode(), state);
                    } else {
                        recurseIntoLoop(closure, blockQueue, states, state, successor);
                    }
                } else if (current.getEndNode() instanceof AbstractEndNode) {
                    AbstractEndNode end = (AbstractEndNode) current.getEndNode();
                    // add the end node and see if the merge is ready for processing
                    AbstractMergeNode merge = end.merge();
                    if (allEndsVisited(states, current, merge)) {
                        ArrayList<StateT> mergedStates = mergeStates(states, state, current, successor, merge);
                        state = closure.merge(successor, mergedStates);
                        next = successor;
                    } else {
                        assert !states.containsKey(end);
                        states.put(end, state);
                    }
                } else {
                    next = successor;
                }
            } else {
                next = processMultipleSuccessors(closure, blockQueue, states, state, successors);
            }
        }
        // get next queued block
        if (next != null) {
            current = next;
        } else if (blockQueue.isEmpty()) {
            return states;
        } else {
            current = blockQueue.removeFirst();
            assert current.getPredecessorCount() == 1;
            assert states.containsKey(current.getBeginNode());
            state = states.removeKey(current.getBeginNode());
        }
    }
}
Also used : CompilationAlarm(org.graalvm.compiler.core.common.util.CompilationAlarm) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ArrayDeque(java.util.ArrayDeque) RetryableBailoutException(org.graalvm.compiler.core.common.RetryableBailoutException) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) Block(org.graalvm.compiler.nodes.cfg.Block) PermanentBailoutException(org.graalvm.compiler.core.common.PermanentBailoutException)

Example 27 with AbstractMergeNode

use of org.graalvm.compiler.nodes.AbstractMergeNode 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)

Example 28 with AbstractMergeNode

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

the class SinglePassNodeIterator method nextQueuedNode.

/**
 * This method is invoked upon not having a (single) next {@link FixedNode} to visit. This
 * method picks such next-node-to-visit from {@link #nodeQueue} and updates {@link #state} with
 * the pre-state for that node.
 *
 * <p>
 * Upon reaching a {@link AbstractMergeNode}, some entries are pruned from {@link #nodeStates}
 * (ie, the entries associated to forward-ends for that merge-node).
 * </p>
 */
private FixedNode nextQueuedNode() {
    if (nodeQueue.isEmpty()) {
        return null;
    }
    PathStart<T> elem = nodeQueue.removeFirst();
    if (elem.node instanceof AbstractMergeNode) {
        AbstractMergeNode merge = (AbstractMergeNode) elem.node;
        state = pruneEntry(merge.forwardEndAt(0));
        ArrayList<T> states = new ArrayList<>(merge.forwardEndCount() - 1);
        for (int i = 1; i < merge.forwardEndCount(); i++) {
            T other = pruneEntry(merge.forwardEndAt(i));
            states.add(other);
        }
        boolean ready = state.merge(merge, states);
        assert ready : "Not a single-pass iterator after all";
        return merge;
    } else {
        AbstractBeginNode begin = elem.node;
        assert begin.predecessor() != null;
        state = elem.stateOnEntry;
        state.afterSplit(begin);
        return begin;
    }
}
Also used : ArrayList(java.util.ArrayList) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 29 with AbstractMergeNode

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

the class MemoryScheduleVerification method processBlock.

@Override
protected EconomicSet<FloatingReadNode> processBlock(Block block, EconomicSet<FloatingReadNode> currentState) {
    AbstractBeginNode beginNode = block.getBeginNode();
    if (beginNode instanceof AbstractMergeNode) {
        AbstractMergeNode abstractMergeNode = (AbstractMergeNode) beginNode;
        for (PhiNode phi : abstractMergeNode.phis()) {
            if (phi instanceof MemoryPhiNode) {
                MemoryPhiNode memoryPhiNode = (MemoryPhiNode) phi;
                addFloatingReadUsages(currentState, memoryPhiNode);
            }
        }
    }
    for (Node n : blockToNodesMap.get(block)) {
        if (n instanceof MemoryCheckpoint) {
            if (n instanceof MemoryCheckpoint.Single) {
                MemoryCheckpoint.Single single = (MemoryCheckpoint.Single) n;
                processLocation(n, single.getLocationIdentity(), currentState);
            } else if (n instanceof MemoryCheckpoint.Multi) {
                MemoryCheckpoint.Multi multi = (MemoryCheckpoint.Multi) n;
                for (LocationIdentity location : multi.getLocationIdentities()) {
                    processLocation(n, location, currentState);
                }
            }
            addFloatingReadUsages(currentState, n);
        } else if (n instanceof MemoryNode) {
            addFloatingReadUsages(currentState, n);
        } else if (n instanceof FloatingReadNode) {
            FloatingReadNode floatingReadNode = (FloatingReadNode) n;
            if (floatingReadNode.getLastLocationAccess() != null && floatingReadNode.getLocationIdentity().isMutable()) {
                if (currentState.contains(floatingReadNode)) {
                    // Floating read was found in the state.
                    currentState.remove(floatingReadNode);
                } else {
                    throw new RuntimeException("Floating read node " + n + " was not found in the state, i.e., it was killed by a memory check point before its place in the schedule. Block=" + block + ", block begin: " + block.getBeginNode() + " block loop: " + block.getLoop() + ", " + blockToNodesMap.get(block).get(0));
                }
            }
        }
    }
    return currentState;
}
Also used : MemoryNode(org.graalvm.compiler.nodes.memory.MemoryNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) FloatingReadNode(org.graalvm.compiler.nodes.memory.FloatingReadNode) MemoryNode(org.graalvm.compiler.nodes.memory.MemoryNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) Node(org.graalvm.compiler.graph.Node) PhiNode(org.graalvm.compiler.nodes.PhiNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) MemoryCheckpoint(org.graalvm.compiler.nodes.memory.MemoryCheckpoint) FloatingReadNode(org.graalvm.compiler.nodes.memory.FloatingReadNode) LocationIdentity(org.graalvm.word.LocationIdentity)

Example 30 with AbstractMergeNode

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

the class JNIJavaCallWrapperMethod method loadAndUnboxArguments.

private List<Pair<ValueNode, ResolvedJavaType>> loadAndUnboxArguments(JNIGraphKit kit, HostedProviders providers, ResolvedJavaMethod invokeMethod, Signature invokeSignature) {
    MetaAccessProvider metaAccess = providers.getMetaAccess();
    List<Pair<ValueNode, ResolvedJavaType>> args = new ArrayList<>();
    int javaIndex = 0;
    javaIndex += metaAccess.lookupJavaType(JNIEnvironment.class).getJavaKind().getSlotCount();
    if (!invokeMethod.isStatic()) {
        JavaKind kind = metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind();
        ValueNode handle = kit.loadLocal(javaIndex, kind);
        ValueNode unboxed = kit.unboxHandle(handle);
        ValueNode receiver;
        ResolvedJavaType receiverClass = invokeMethod.getDeclaringClass();
        if (invokeMethod.isConstructor()) {
            /*
                 * Our target method is a constructor and we might be called via `NewObject`, in
                 * which case we need to allocate the object before calling the constructor. We can
                 * detect when this is the case because unlike with `Call<Type>Method`, we are
                 * passed the object hub of our target class in place of the receiver object.
                 */
            Constant hub = providers.getConstantReflection().asObjectHub(receiverClass);
            ConstantNode hubNode = kit.createConstant(hub, JavaKind.Object);
            kit.startIf(kit.unique(new ObjectEqualsNode(unboxed, hubNode)), BranchProbabilityNode.FAST_PATH_PROBABILITY);
            kit.thenPart();
            ValueNode created = kit.append(new NewInstanceNode(receiverClass, true));
            AbstractMergeNode merge = kit.endIf();
            receiver = kit.unique(new ValuePhiNode(StampFactory.object(), merge, new ValueNode[] { created, unboxed }));
        } else {
            receiver = unboxed;
        }
        args.add(Pair.create(receiver, receiverClass));
    }
    javaIndex += metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind().getSlotCount();
    if (nonVirtual) {
        javaIndex += metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind().getSlotCount();
    }
    javaIndex += metaAccess.lookupJavaType(JNIMethodId.class).getJavaKind().getSlotCount();
    int count = invokeSignature.getParameterCount(false);
    if (callVariant == CallVariant.VARARGS) {
        for (int i = 0; i < count; i++) {
            ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
            JavaKind kind = type.getJavaKind();
            JavaKind loadKind = kind;
            if (loadKind == JavaKind.Float) {
                // C varargs promote float to double
                loadKind = JavaKind.Double;
            }
            ValueNode value = kit.loadLocal(javaIndex, loadKind);
            if (kind == JavaKind.Float) {
                value = kit.unique(new FloatConvertNode(FloatConvert.D2F, value));
            } else if (kind.isObject()) {
                value = kit.unboxHandle(value);
            }
            args.add(Pair.create(value, type));
            javaIndex += loadKind.getSlotCount();
        }
    } else if (callVariant == CallVariant.ARRAY) {
        ResolvedJavaType elementType = metaAccess.lookupJavaType(JNIValue.class);
        int elementSize = SizeOf.get(JNIValue.class);
        ValueNode array = kit.loadLocal(javaIndex, elementType.getJavaKind());
        for (int i = 0; i < count; i++) {
            ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
            JavaKind readKind = type.getJavaKind();
            StructFieldInfo fieldInfo = getJNIValueOffsetOf(elementType, readKind);
            int offset = i * elementSize + fieldInfo.getOffsetInfo().getProperty();
            ConstantNode offsetConstant = kit.createConstant(JavaConstant.forInt(offset), providers.getWordTypes().getWordKind());
            OffsetAddressNode address = kit.unique(new OffsetAddressNode(array, offsetConstant));
            LocationIdentity locationIdentity = fieldInfo.getLocationIdentity();
            if (locationIdentity == null) {
                locationIdentity = LocationIdentity.any();
            }
            Stamp readStamp = getNarrowStamp(providers, readKind);
            ValueNode value = kit.append(new CInterfaceReadNode(address, locationIdentity, readStamp, BarrierType.NONE, "args[" + i + "]"));
            JavaKind stackKind = readKind.getStackKind();
            if (readKind != stackKind) {
                assert stackKind.getBitCount() > readKind.getBitCount() : "read kind must be narrower than stack kind";
                if (readKind.isUnsigned()) {
                    // needed or another op may illegally sign-extend
                    value = kit.unique(new ZeroExtendNode(value, stackKind.getBitCount()));
                } else {
                    value = kit.unique(new SignExtendNode(value, stackKind.getBitCount()));
                }
            } else if (readKind.isObject()) {
                value = kit.unboxHandle(value);
            }
            args.add(Pair.create(value, type));
        }
    } else if (callVariant == CallVariant.VA_LIST) {
        ValueNode valist = kit.loadLocal(javaIndex, metaAccess.lookupJavaType(WordBase.class).getJavaKind());
        for (int i = 0; i < count; i++) {
            ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
            JavaKind loadKind = type.getJavaKind();
            if (loadKind.isObject()) {
                loadKind = providers.getWordTypes().getWordKind();
            }
            ValueNode value = kit.append(new VaListNextArgNode(loadKind, valist));
            if (type.getJavaKind().isObject()) {
                value = kit.unboxHandle(value);
            }
            args.add(Pair.create(value, type));
        }
    } else {
        throw VMError.unsupportedFeature("Call variant: " + callVariant);
    }
    return args;
}
Also used : NewInstanceNode(org.graalvm.compiler.nodes.java.NewInstanceNode) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) Constant(jdk.vm.ci.meta.Constant) JavaConstant(jdk.vm.ci.meta.JavaConstant) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) CInterfaceReadNode(com.oracle.svm.core.graal.nodes.CInterfaceReadNode) ArrayList(java.util.ArrayList) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) LogicConstantNode(org.graalvm.compiler.nodes.LogicConstantNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) JNIValue(com.oracle.svm.jni.nativeapi.JNIValue) LocationIdentity(org.graalvm.word.LocationIdentity) JNIObjectHandle(com.oracle.svm.jni.nativeapi.JNIObjectHandle) Pair(org.graalvm.collections.Pair) JavaKind(jdk.vm.ci.meta.JavaKind) VaListNextArgNode(com.oracle.svm.core.graal.nodes.VaListNextArgNode) Stamp(org.graalvm.compiler.core.common.type.Stamp) ObjectEqualsNode(org.graalvm.compiler.nodes.calc.ObjectEqualsNode) StructFieldInfo(com.oracle.svm.hosted.c.info.StructFieldInfo) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ZeroExtendNode(org.graalvm.compiler.nodes.calc.ZeroExtendNode) JNIMethodId(com.oracle.svm.jni.nativeapi.JNIMethodId) FloatConvertNode(org.graalvm.compiler.nodes.calc.FloatConvertNode) OffsetAddressNode(org.graalvm.compiler.nodes.memory.address.OffsetAddressNode) JNIEnvironment(com.oracle.svm.jni.nativeapi.JNIEnvironment) ValueNode(org.graalvm.compiler.nodes.ValueNode) MetaAccessProvider(jdk.vm.ci.meta.MetaAccessProvider)

Aggregations

AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)59 FixedNode (org.graalvm.compiler.nodes.FixedNode)31 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)28 EndNode (org.graalvm.compiler.nodes.EndNode)24 Node (org.graalvm.compiler.graph.Node)22 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)22 ValueNode (org.graalvm.compiler.nodes.ValueNode)22 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)20 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)19 PhiNode (org.graalvm.compiler.nodes.PhiNode)18 MergeNode (org.graalvm.compiler.nodes.MergeNode)16 ValuePhiNode (org.graalvm.compiler.nodes.ValuePhiNode)14 ControlSplitNode (org.graalvm.compiler.nodes.ControlSplitNode)13 LoopEndNode (org.graalvm.compiler.nodes.LoopEndNode)13 LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)13 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)12 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)11 ArrayList (java.util.ArrayList)10 FrameState (org.graalvm.compiler.nodes.FrameState)10 IfNode (org.graalvm.compiler.nodes.IfNode)9