Search in sources :

Example 11 with ValuePhiNode

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

the class JNIJavaCallWrapperMethod method buildGraph.

@Override
public StructuredGraph buildGraph(DebugContext debug, ResolvedJavaMethod method, HostedProviders providers, Purpose purpose) {
    UniverseMetaAccess metaAccess = (UniverseMetaAccess) providers.getMetaAccess();
    JNIGraphKit kit = new JNIGraphKit(debug, providers, method);
    StructuredGraph graph = kit.getGraph();
    FrameStateBuilder state = new FrameStateBuilder(null, method, graph);
    state.initializeForMethodStart(null, true, providers.getGraphBuilderPlugins());
    JavaKind vmThreadKind = metaAccess.lookupJavaType(JNIEnvironment.class).getJavaKind();
    ValueNode vmThread = kit.loadLocal(0, vmThreadKind);
    kit.append(new CEntryPointEnterNode(EnterAction.Enter, vmThread));
    ResolvedJavaMethod invokeMethod = providers.getMetaAccess().lookupJavaMethod(reflectMethod);
    Signature invokeSignature = invokeMethod.getSignature();
    List<Pair<ValueNode, ResolvedJavaType>> argsWithTypes = loadAndUnboxArguments(kit, providers, invokeMethod, invokeSignature);
    JavaKind returnKind = invokeSignature.getReturnKind();
    if (invokeMethod.isConstructor()) {
        // return `this` to implement NewObject
        assert returnKind == JavaKind.Void;
        returnKind = JavaKind.Object;
    }
    IfNode ifNode = kit.startIf(null, BranchProbabilityNode.FAST_PATH_PROBABILITY);
    kit.thenPart();
    LogicNode typeChecks = LogicConstantNode.tautology(kit.getGraph());
    ValueNode[] args = new ValueNode[argsWithTypes.size()];
    for (int i = 0; i < argsWithTypes.size(); i++) {
        ValueNode value = argsWithTypes.get(i).getLeft();
        ResolvedJavaType type = argsWithTypes.get(i).getRight();
        if (!type.isPrimitive() && !type.isJavaLangObject()) {
            TypeReference typeRef = TypeReference.createTrusted(kit.getAssumptions(), type);
            LogicNode instanceOf = kit.unique(InstanceOfNode.createAllowNull(typeRef, value, null, null));
            typeChecks = LogicNode.and(typeChecks, instanceOf, BranchProbabilityNode.FAST_PATH_PROBABILITY);
            FixedGuardNode guard = kit.append(new FixedGuardNode(instanceOf, DeoptimizationReason.ClassCastException, DeoptimizationAction.None, false));
            value = kit.append(PiNode.create(value, StampFactory.object(typeRef), guard));
        }
        args[i] = value;
    }
    // safe because logic nodes are floating
    ifNode.setCondition(typeChecks);
    InvokeKind kind = // 
    invokeMethod.isStatic() ? // 
    InvokeKind.Static : ((nonVirtual || invokeMethod.isConstructor()) ? InvokeKind.Special : InvokeKind.Virtual);
    ValueNode invokeResult = createInvoke(kit, invokeMethod, kind, state, kit.bci(), args);
    if (invokeMethod.isConstructor()) {
        // return `this` to implement NewObject
        invokeResult = args[0];
    }
    // illegal parameter types
    kit.elsePart();
    ConstantNode exceptionObject = kit.createObject(cachedArgumentClassCastException);
    kit.retainPendingException(exceptionObject);
    ValueNode typeMismatchValue = null;
    if (returnKind != JavaKind.Void) {
        typeMismatchValue = kit.unique(ConstantNode.defaultForKind(returnKind.getStackKind()));
    }
    AbstractMergeNode merge = kit.endIf();
    ValueNode returnValue = null;
    if (returnKind != JavaKind.Void) {
        ValueNode[] inputs = { invokeResult, typeMismatchValue };
        returnValue = kit.getGraph().addWithoutUnique(new ValuePhiNode(invokeResult.stamp(NodeView.DEFAULT), merge, inputs));
        state.push(returnKind, returnValue);
    }
    merge.setStateAfter(state.create(kit.bci(), merge));
    if (returnKind != JavaKind.Void) {
        state.pop(returnKind);
        if (returnKind.isObject()) {
            returnValue = kit.boxObjectInLocalHandle(returnValue);
        }
    }
    kit.append(new CEntryPointLeaveNode(LeaveAction.Leave));
    kit.createReturn(returnValue, returnKind);
    assert graph.verify();
    return graph;
}
Also used : UniverseMetaAccess(com.oracle.graal.pointsto.infrastructure.UniverseMetaAccess) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) IfNode(org.graalvm.compiler.nodes.IfNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) InvokeKind(org.graalvm.compiler.nodes.CallTargetNode.InvokeKind) CEntryPointLeaveNode(com.oracle.svm.core.graal.nodes.CEntryPointLeaveNode) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) LogicConstantNode(org.graalvm.compiler.nodes.LogicConstantNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) JNIEnvironment(com.oracle.svm.jni.nativeapi.JNIEnvironment) CEntryPointEnterNode(com.oracle.svm.core.graal.nodes.CEntryPointEnterNode) Signature(jdk.vm.ci.meta.Signature) ValueNode(org.graalvm.compiler.nodes.ValueNode) FrameStateBuilder(org.graalvm.compiler.java.FrameStateBuilder) LogicNode(org.graalvm.compiler.nodes.LogicNode) TypeReference(org.graalvm.compiler.core.common.type.TypeReference) ResolvedJavaMethod(jdk.vm.ci.meta.ResolvedJavaMethod) JavaKind(jdk.vm.ci.meta.JavaKind) Pair(org.graalvm.collections.Pair)

Example 12 with ValuePhiNode

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

the class JNIJavaCallWrapperMethod method createInvoke.

private static ValueNode createInvoke(JNIGraphKit kit, ResolvedJavaMethod invokeMethod, InvokeKind kind, FrameStateBuilder state, int bci, ValueNode... args) {
    int exceptionEdgeBci = kit.bci();
    InvokeWithExceptionNode invoke = kit.startInvokeWithException(invokeMethod, kind, state, bci, exceptionEdgeBci, args);
    kit.exceptionPart();
    ExceptionObjectNode exceptionObject = kit.exceptionObject();
    kit.retainPendingException(exceptionObject);
    ValueNode exceptionValue = null;
    if (invoke.getStackKind() != JavaKind.Void) {
        exceptionValue = kit.unique(ConstantNode.defaultForKind(invoke.getStackKind()));
    }
    AbstractMergeNode merge = kit.endInvokeWithException();
    ValueNode returnValue = null;
    JavaKind returnKind = invokeMethod.getSignature().getReturnKind();
    if (invoke.getStackKind() != JavaKind.Void) {
        ValueNode[] inputs = { invoke, exceptionValue };
        returnValue = kit.getGraph().addWithoutUnique(new ValuePhiNode(invoke.stamp(NodeView.DEFAULT), merge, inputs));
        state.push(returnKind, returnValue);
    }
    merge.setStateAfter(state.create(bci, merge));
    if (invoke.getStackKind() != JavaKind.Void) {
        state.pop(returnKind);
    }
    return returnValue;
}
Also used : InvokeWithExceptionNode(org.graalvm.compiler.nodes.InvokeWithExceptionNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) JavaKind(jdk.vm.ci.meta.JavaKind)

Example 13 with ValuePhiNode

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

the class JNIPrimitiveArrayOperationMethod method newArray.

private ValueNode newArray(HostedProviders providers, JNIGraphKit kit, List<ValueNode> arguments) {
    ResolvedJavaType elementType = providers.getMetaAccess().lookupJavaType(elementKind.toJavaClass());
    ValueNode length = arguments.get(1);
    ConstantNode zero = kit.createInt(0);
    kit.startIf(new IntegerLessThanNode(length, zero), BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY);
    kit.thenPart();
    ValueNode nullHandle = kit.createConstant(JavaConstant.INT_0, providers.getWordTypes().getWordKind());
    kit.elsePart();
    ValueNode array = kit.append(new NewArrayNode(elementType, length, true));
    ValueNode arrayHandle = kit.boxObjectInLocalHandle(array);
    AbstractMergeNode merge = kit.endIf();
    Stamp handleStamp = providers.getWordTypes().getWordStamp(providers.getMetaAccess().lookupJavaType(JNIObjectHandle.class));
    return kit.unique(new ValuePhiNode(handleStamp, merge, new ValueNode[] { nullHandle, arrayHandle }));
}
Also used : ConstantNode(org.graalvm.compiler.nodes.ConstantNode) NewArrayNode(org.graalvm.compiler.nodes.java.NewArrayNode) Stamp(org.graalvm.compiler.core.common.type.Stamp) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) IntegerLessThanNode(org.graalvm.compiler.nodes.calc.IntegerLessThanNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) JNIObjectHandle(com.oracle.svm.jni.nativeapi.JNIObjectHandle)

Example 14 with ValuePhiNode

use of org.graalvm.compiler.nodes.ValuePhiNode 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 15 with ValuePhiNode

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

the class LoopEx method findInductionVariables.

/**
 * Collect all the basic induction variables for the loop and the find any induction variables
 * which are derived from the basic ones.
 *
 * @param loop
 * @return a map from node to induction variable
 */
private static EconomicMap<Node, InductionVariable> findInductionVariables(LoopEx loop) {
    EconomicMap<Node, InductionVariable> ivs = EconomicMap.create(Equivalence.IDENTITY);
    Queue<InductionVariable> scanQueue = new LinkedList<>();
    LoopBeginNode loopBegin = loop.loopBegin();
    AbstractEndNode forwardEnd = loopBegin.forwardEnd();
    for (PhiNode phi : loopBegin.valuePhis()) {
        ValueNode backValue = phi.singleBackValueOrThis();
        if (backValue == phi) {
            continue;
        }
        ValueNode stride = addSub(loop, backValue, phi);
        if (stride != null) {
            BasicInductionVariable biv = new BasicInductionVariable(loop, (ValuePhiNode) phi, phi.valueAt(forwardEnd), stride, (BinaryArithmeticNode<?>) backValue);
            ivs.put(phi, biv);
            scanQueue.add(biv);
        }
    }
    while (!scanQueue.isEmpty()) {
        InductionVariable baseIv = scanQueue.remove();
        ValueNode baseIvNode = baseIv.valueNode();
        for (ValueNode op : baseIvNode.usages().filter(ValueNode.class)) {
            if (loop.isOutsideLoop(op)) {
                continue;
            }
            if (op.usages().count() == 1 && op.usages().first() == baseIvNode) {
                /*
                     * This is just the base induction variable increment with no other uses so
                     * don't bother reporting it.
                     */
                continue;
            }
            InductionVariable iv = null;
            ValueNode offset = addSub(loop, op, baseIvNode);
            ValueNode scale;
            if (offset != null) {
                iv = new DerivedOffsetInductionVariable(loop, baseIv, offset, (BinaryArithmeticNode<?>) op);
            } else if (op instanceof NegateNode) {
                iv = new DerivedScaledInductionVariable(loop, baseIv, (NegateNode) op);
            } else if ((scale = mul(loop, op, baseIvNode)) != null) {
                iv = new DerivedScaledInductionVariable(loop, baseIv, scale, op);
            } else {
                boolean isValidConvert = op instanceof PiNode || op instanceof SignExtendNode;
                if (!isValidConvert && op instanceof ZeroExtendNode) {
                    ZeroExtendNode zeroExtendNode = (ZeroExtendNode) op;
                    isValidConvert = zeroExtendNode.isInputAlwaysPositive() || ((IntegerStamp) zeroExtendNode.stamp(NodeView.DEFAULT)).isPositive();
                }
                if (isValidConvert) {
                    iv = new DerivedConvertedInductionVariable(loop, baseIv, op.stamp(NodeView.DEFAULT), op);
                }
            }
            if (iv != null) {
                ivs.put(op, iv);
                scanQueue.offer(iv);
            }
        }
    }
    return ivs;
}
Also used : ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) ValueAnchorNode(org.graalvm.compiler.nodes.extended.ValueAnchorNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) IntegerLessThanNode(org.graalvm.compiler.nodes.calc.IntegerLessThanNode) NegateNode(org.graalvm.compiler.nodes.calc.NegateNode) ZeroExtendNode(org.graalvm.compiler.nodes.calc.ZeroExtendNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) IfNode(org.graalvm.compiler.nodes.IfNode) 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) BinaryArithmeticNode(org.graalvm.compiler.nodes.calc.BinaryArithmeticNode) FullInfopointNode(org.graalvm.compiler.nodes.FullInfopointNode) MulNode(org.graalvm.compiler.nodes.calc.MulNode) CompareNode(org.graalvm.compiler.nodes.calc.CompareNode) LeftShiftNode(org.graalvm.compiler.nodes.calc.LeftShiftNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) IntegerEqualsNode(org.graalvm.compiler.nodes.calc.IntegerEqualsNode) AddNode(org.graalvm.compiler.nodes.calc.AddNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) IntegerBelowNode(org.graalvm.compiler.nodes.calc.IntegerBelowNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) SubNode(org.graalvm.compiler.nodes.calc.SubNode) Node(org.graalvm.compiler.graph.Node) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) PiNode(org.graalvm.compiler.nodes.PiNode) ZeroExtendNode(org.graalvm.compiler.nodes.calc.ZeroExtendNode) BinaryArithmeticNode(org.graalvm.compiler.nodes.calc.BinaryArithmeticNode) LinkedList(java.util.LinkedList) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) IntegerStamp(org.graalvm.compiler.core.common.type.IntegerStamp) ValueNode(org.graalvm.compiler.nodes.ValueNode) NegateNode(org.graalvm.compiler.nodes.calc.NegateNode)

Aggregations

ValuePhiNode (org.graalvm.compiler.nodes.ValuePhiNode)24 ValueNode (org.graalvm.compiler.nodes.ValueNode)18 PhiNode (org.graalvm.compiler.nodes.PhiNode)12 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)11 Node (org.graalvm.compiler.graph.Node)9 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)8 FixedNode (org.graalvm.compiler.nodes.FixedNode)8 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)7 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)6 LogicNode (org.graalvm.compiler.nodes.LogicNode)6 ResolvedJavaType (jdk.vm.ci.meta.ResolvedJavaType)5 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)5 EndNode (org.graalvm.compiler.nodes.EndNode)5 JavaKind (jdk.vm.ci.meta.JavaKind)4 IfNode (org.graalvm.compiler.nodes.IfNode)4 ArrayList (java.util.ArrayList)3 DeoptimizeNode (org.graalvm.compiler.nodes.DeoptimizeNode)3 FixedGuardNode (org.graalvm.compiler.nodes.FixedGuardNode)3 LogicConstantNode (org.graalvm.compiler.nodes.LogicConstantNode)3 MergeNode (org.graalvm.compiler.nodes.MergeNode)3