Search in sources :

Example 26 with ParameterNode

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

the class ReinterpretStampLongToDoubleTest method run.

@Test
public void run() {
    ParameterNode param = new ParameterNode(0, StampPair.createSingle(inputStamp));
    ValueNode reinterpret = ReinterpretNode.create(JavaKind.Double, param, NodeView.DEFAULT);
    reinterpret.inferStamp();
    FloatStamp resultStamp = (FloatStamp) reinterpret.stamp(NodeView.DEFAULT);
    Assert.assertEquals(Double.SIZE, resultStamp.getBits());
    for (long input : interestingLongs) {
        double result = Double.longBitsToDouble(input);
        if (inputStamp.contains(input) && !resultStamp.contains(result)) {
            Assert.fail(String.format("value 0x%x (%f) is in input stamp, but not in result stamp (%s)", input, result, resultStamp));
        }
    }
}
Also used : ParameterNode(org.graalvm.compiler.nodes.ParameterNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) FloatStamp(org.graalvm.compiler.core.common.type.FloatStamp) Test(org.junit.Test)

Example 27 with ParameterNode

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

the class StrengthenStampsPhase method strengthenStamp.

private Stamp strengthenStamp(ValueNode node, JavaTypeProfile typeProfile) {
    ObjectStamp oldStamp = (ObjectStamp) node.stamp(NodeView.DEFAULT);
    HostedType oldType = toHosted(oldStamp.type());
    if (oldStamp.alwaysNull()) {
        /* We cannot make that more precise. */
        return oldStamp;
    }
    boolean nonNull = oldStamp.nonNull() || typeProfile.getNullSeen() == TriState.FALSE;
    ProfiledType[] exactTypes = typeProfile.getTypes();
    if (exactTypes.length == 1) {
        ResolvedJavaType exactType = exactTypes[0].getType();
        assert oldType == null || oldType.isAssignableFrom(exactType);
        if (!oldStamp.isExactType() || !exactType.equals(oldType) || nonNull != oldStamp.nonNull()) {
            TypeReference typeRef = TypeReference.createExactTrusted(toTarget(exactType));
            return nonNull ? StampFactory.objectNonNull(typeRef) : StampFactory.object(typeRef);
        } else {
            return oldStamp;
        }
    }
    if (exactTypes.length == 0) {
        if (!nonNull) {
            return StampFactory.alwaysNull();
        } else {
            /*
                 * The code after the node is unreachable. We just insert a always-failing guard
                 * after the node and let dead code elimination remove everything after the node.
                 */
            StructuredGraph graph = node.graph();
            FixedWithNextNode insertionPoint;
            if (node instanceof ParameterNode) {
                /* The whole method is unreachable. */
                insertionPoint = graph.start();
            } else if (node instanceof InvokeWithExceptionNode) {
                /* The invoked method never returns normally (but can throw an exception). */
                insertionPoint = ((InvokeWithExceptionNode) node).next();
            } else {
                insertionPoint = (FixedWithNextNode) node;
            }
            graph.addAfterFixed(insertionPoint, graph.add(new FixedGuardNode(LogicConstantNode.forBoolean(true, graph), DeoptimizationReason.UnreachedCode, DeoptimizationAction.None, true)));
            return oldStamp;
        }
    }
    ResolvedJavaType baseType;
    if (oldStamp.isExactType()) {
        /* Base type cannot be more precise. */
        baseType = oldType;
    } else {
        assert exactTypes.length > 1;
        assert oldType == null || oldType.isAssignableFrom(exactTypes[0].getType());
        baseType = exactTypes[0].getType();
        for (int i = 1; i < exactTypes.length; i++) {
            assert oldType == null || oldType.isAssignableFrom(exactTypes[i].getType());
            baseType = baseType.findLeastCommonAncestor(exactTypes[i].getType());
        }
        if (oldType != null && !oldType.isAssignableFrom(baseType)) {
            /*
                 * When the original stamp is an interface type, we do not want to weaken that type
                 * with the common base class of all implementation types (which could even be
                 * java.lang.Object).
                 */
            baseType = oldType;
        }
    }
    if (!baseType.equals(oldType) || nonNull != oldStamp.nonNull()) {
        TypeReference typeRef = TypeReference.createTrustedWithoutAssumptions(toTarget(baseType));
        return nonNull ? StampFactory.objectNonNull(typeRef) : StampFactory.object(typeRef);
    }
    return oldStamp;
}
Also used : FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) ProfiledType(jdk.vm.ci.meta.JavaTypeProfile.ProfiledType) ObjectStamp(org.graalvm.compiler.core.common.type.ObjectStamp) AbstractObjectStamp(org.graalvm.compiler.core.common.type.AbstractObjectStamp) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) HostedType(com.oracle.svm.hosted.meta.HostedType) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) InvokeWithExceptionNode(org.graalvm.compiler.nodes.InvokeWithExceptionNode) TypeReference(org.graalvm.compiler.core.common.type.TypeReference)

Example 28 with ParameterNode

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

the class AssertValueNode method insert.

protected static void insert(ValueNode input, AssertValueNode assertionNode) {
    StructuredGraph graph = input.graph();
    /* Find the insertion point where we want to add the assertion node. */
    FixedWithNextNode insertionPoint;
    if (input instanceof ParameterNode) {
        insertionPoint = graph.start();
    } else if (input instanceof InvokeWithExceptionNode) {
        insertionPoint = ((InvokeWithExceptionNode) input).next();
    } else if (input instanceof FixedWithNextNode) {
        insertionPoint = (FixedWithNextNode) input;
    } else {
        throw shouldNotReachHere("Node is not fixed: " + input);
    }
    /*
         * When inserting after an invoke that is also a loop exit, a proxy node is inserted between
         * the invoke and every usage. We need to be after this proxy node to avoid unschedulable
         * graphs.
         */
    ProxyNode proxyUsage = null;
    boolean otherUsages = false;
    for (Node usage : input.usages()) {
        if (usage instanceof ProxyNode && ((ProxyNode) usage).proxyPoint() == insertionPoint) {
            assert proxyUsage == null : "can have only one proxy";
            proxyUsage = (ProxyNode) usage;
        } else if (!(usage instanceof FrameState)) {
            otherUsages = true;
        }
    }
    assert proxyUsage == null || otherUsages == false : "cannot have other usages when having a proxy usage";
    ValueNode assertInput = proxyUsage != null ? proxyUsage : input;
    /*
         * Replace the object at usages. We do not process usages at the frame state because it
         * could be the stateAfter() of the insertion point. Since frame states are not doing
         * anything in code, this is not a loss of assertion precision.
         */
    for (Node usage : assertInput.usages().snapshot()) {
        if (!(usage instanceof FrameState)) {
            usage.replaceFirstInput(assertInput, assertionNode);
        }
    }
    /*
         * Set the input object of the assertion node, now that all other usages have been replaced.
         */
    assertionNode.updateUsages(assertionNode.input, assertInput);
    assertionNode.input = assertInput;
    /* Insert assertion node in graph. */
    graph.addAfterFixed(insertionPoint, assertionNode);
}
Also used : ProxyNode(org.graalvm.compiler.nodes.ProxyNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) InvokeWithExceptionNode(org.graalvm.compiler.nodes.InvokeWithExceptionNode) InvokeWithExceptionNode(org.graalvm.compiler.nodes.InvokeWithExceptionNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Node(org.graalvm.compiler.graph.Node) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) FrameState(org.graalvm.compiler.nodes.FrameState)

Example 29 with ParameterNode

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

the class IntrinsifyMethodHandlesInvocationPlugin method processInvokeWithMethodHandle.

@SuppressWarnings("try")
private void processInvokeWithMethodHandle(GraphBuilderContext b, BytecodeProvider bytecodeProvider, ResolvedJavaMethod methodHandleMethod, ValueNode[] methodHandleArguments) {
    Plugins graphBuilderPlugins = new Plugins(((ReplacementsImpl) originalProviders.getReplacements()).getGraphBuilderPlugins());
    registerInvocationPlugins(graphBuilderPlugins.getInvocationPlugins(), bytecodeProvider);
    graphBuilderPlugins.prependParameterPlugin(new MethodHandlesParameterPlugin(methodHandleArguments));
    graphBuilderPlugins.clearInlineInvokePlugins();
    graphBuilderPlugins.prependInlineInvokePlugin(new MethodHandlesInlineInvokePlugin());
    graphBuilderPlugins.prependNodePlugin(new MethodHandlePlugin(originalProviders.getConstantReflection().getMethodHandleAccess(), false));
    /* We do all the word type rewriting because parameters to the lambda can be word types. */
    SnippetReflectionProvider originalSnippetReflection = GraalAccess.getOriginalSnippetReflection();
    WordOperationPlugin wordOperationPlugin = new WordOperationPlugin(originalSnippetReflection, new WordTypes(originalProviders.getMetaAccess(), FrameAccess.getWordKind()));
    graphBuilderPlugins.appendInlineInvokePlugin(wordOperationPlugin);
    graphBuilderPlugins.appendTypePlugin(wordOperationPlugin);
    graphBuilderPlugins.appendTypePlugin(new TrustedInterfaceTypePlugin());
    graphBuilderPlugins.appendNodePlugin(wordOperationPlugin);
    GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getSnippetDefault(graphBuilderPlugins);
    GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(originalProviders.getMetaAccess(), originalProviders.getStampProvider(), originalProviders.getConstantReflection(), originalProviders.getConstantFieldProvider(), graphBuilderConfig, OptimisticOptimizations.NONE, null);
    DebugContext debug = b.getDebug();
    StructuredGraph graph = new StructuredGraph.Builder(b.getOptions(), debug).method(toOriginal(methodHandleMethod)).build();
    try (DebugContext.Scope s = debug.scope("IntrinsifyMethodHandles", graph)) {
        graphBuilder.apply(graph);
        /*
             * We do not care about the improved type information from Pi nodes, so we just delete
             * them to simplify our graph.
             */
        for (PiNode pi : graph.getNodes(PiNode.TYPE)) {
            pi.replaceAndDelete(pi.object());
        }
        /*
             * Support for MethodHandle that adapt the input type to a more generic type, i.e., a
             * MethodHandle that does a dynamic type check on a parameter.
             */
        for (UnaryOpLogicNode node : graph.getNodes().filter(UnaryOpLogicNode.class).filter(v -> v instanceof IsNullNode || v instanceof InstanceOfNode)) {
            ValueNode value = node.getValue();
            if (value instanceof ParameterNode) {
                /*
                     * We just assume that the InstanceOfNode or IsNullNode are used in an If and
                     * the true-successor is actually the branch we want. If that assumption is
                     * wrong, nothing bad happens - we will just continue to report the invocation
                     * as unsupported because the updated stamp for the parameter will not simplify
                     * the graph.
                     */
                if (node instanceof InstanceOfNode) {
                    InstanceOfNode inst = (InstanceOfNode) node;
                    TypeReference typeRef = inst.type();
                    value.setStamp(new ObjectStamp(typeRef.getType(), typeRef.isExact(), !inst.allowsNull(), false));
                } else {
                    assert node instanceof IsNullNode;
                    ResolvedJavaType type = value.stamp(NodeView.DEFAULT).javaType(originalProviders.getMetaAccess());
                    value.setStamp(new ObjectStamp(type, false, /* non-null */
                    true, false));
                }
            }
        }
        /*
             * The canonicalizer converts unsafe field accesses for get/set method handles back to
             * high-level field load and store nodes.
             */
        new CanonicalizerPhase().apply(graph, new PhaseContext(originalProviders));
        for (FixedGuardNode guard : graph.getNodes(FixedGuardNode.TYPE)) {
            if (guard.next() instanceof AccessFieldNode && guard.condition() instanceof IsNullNode && guard.isNegated() && ((IsNullNode) guard.condition()).getValue() == ((AccessFieldNode) guard.next()).object()) {
                /*
                     * Method handles to load and stores fields have null checks. Remove them, since
                     * the null check is implicitly done by the field access.
                     */
                GraphUtil.removeFixedWithUnusedInputs(guard);
            }
        }
        debug.dump(DebugContext.VERY_DETAILED_LEVEL, graph, "Final intrinisfication graph");
        /*
             * After parsing (and recursive inlining during parsing), the graph must contain only
             * one invocation (and therefore only one MethodCallTargetNode), plus the parameters,
             * constants, start, and return nodes.
             */
        Node singleFunctionality = null;
        ReturnNode singleReturn = null;
        for (Node node : graph.getNodes()) {
            if (node == graph.start() || node instanceof ParameterNode || node instanceof ConstantNode || node instanceof FrameState) {
                /* Ignore the allowed framework around the nodes we care about. */
                continue;
            } else if (node instanceof Invoke) {
                /* We check the MethodCallTargetNode, so we can ignore the invoke. */
                continue;
            } else if ((node instanceof MethodCallTargetNode || node instanceof LoadFieldNode || node instanceof StoreFieldNode) && singleFunctionality == null) {
                singleFunctionality = node;
                continue;
            } else if (node instanceof ReturnNode && singleReturn == null) {
                singleReturn = (ReturnNode) node;
                continue;
            }
            throw new UnsupportedFeatureException("Invoke with MethodHandle argument could not be reduced to at most a single call: " + methodHandleMethod.format("%H.%n(%p)"));
        }
        if (singleFunctionality instanceof MethodCallTargetNode) {
            MethodCallTargetNode singleCallTarget = (MethodCallTargetNode) singleFunctionality;
            assert singleReturn.result() == null || singleReturn.result() == singleCallTarget.invoke();
            /*
                 * Replace the originalTarget with the replacementTarget. Note that the
                 * replacementTarget node belongs to a different graph than originalTarget, so we
                 * need to match parameter back to the original graph and allocate a new
                 * MethodCallTargetNode for the original graph.
                 */
            ValueNode[] replacedArguments = new ValueNode[singleCallTarget.arguments().size()];
            for (int i = 0; i < replacedArguments.length; i++) {
                replacedArguments[i] = lookup(b, methodHandleArguments, singleCallTarget.arguments().get(i));
            }
            b.handleReplacedInvoke(singleCallTarget.invokeKind(), lookup(singleCallTarget.targetMethod()), replacedArguments, false);
        } else if (singleFunctionality instanceof LoadFieldNode) {
            LoadFieldNode fieldLoad = (LoadFieldNode) singleFunctionality;
            b.addPush(b.getInvokeReturnType().getJavaKind(), LoadFieldNode.create(null, lookup(b, methodHandleArguments, fieldLoad.object()), lookup(fieldLoad.field())));
        } else if (singleFunctionality instanceof StoreFieldNode) {
            StoreFieldNode fieldStore = (StoreFieldNode) singleFunctionality;
            b.add(new StoreFieldNode(lookup(b, methodHandleArguments, fieldStore.object()), lookup(fieldStore.field()), lookup(b, methodHandleArguments, fieldStore.value())));
        } else if (singleReturn.result() != null) {
            /* Replace the invocation with he constant result. */
            JavaConstant constantResult = singleReturn.result().asJavaConstant();
            assert b.getInvokeReturnType().getJavaKind() == constantResult.getJavaKind();
            b.addPush(constantResult.getJavaKind(), ConstantNode.forConstant(lookup(constantResult), universeProviders.getMetaAccess()));
        } else {
            /* No invoke and no return value, so nothing to do. */
            assert b.getInvokeReturnType().getJavaKind() == JavaKind.Void;
        }
    } catch (Throwable ex) {
        throw debug.handle(ex);
    }
}
Also used : ObjectStamp(org.graalvm.compiler.core.common.type.ObjectStamp) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) AccessFieldNode(org.graalvm.compiler.nodes.java.AccessFieldNode) ReturnNode(org.graalvm.compiler.nodes.ReturnNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) PiNode(org.graalvm.compiler.nodes.PiNode) UnaryOpLogicNode(org.graalvm.compiler.nodes.UnaryOpLogicNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) FloatingNode(org.graalvm.compiler.nodes.calc.FloatingNode) LoadFieldNode(org.graalvm.compiler.nodes.java.LoadFieldNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) InstanceOfNode(org.graalvm.compiler.nodes.java.InstanceOfNode) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) StoreFieldNode(org.graalvm.compiler.nodes.java.StoreFieldNode) Node(org.graalvm.compiler.graph.Node) WordTypes(org.graalvm.compiler.word.WordTypes) JavaConstant(jdk.vm.ci.meta.JavaConstant) PiNode(org.graalvm.compiler.nodes.PiNode) FrameState(org.graalvm.compiler.nodes.FrameState) UnaryOpLogicNode(org.graalvm.compiler.nodes.UnaryOpLogicNode) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) Invoke(org.graalvm.compiler.nodes.Invoke) PhaseContext(org.graalvm.compiler.phases.tiers.PhaseContext) SnippetReflectionProvider(org.graalvm.compiler.api.replacements.SnippetReflectionProvider) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) TypeReference(org.graalvm.compiler.core.common.type.TypeReference) GraphBuilderPhase(org.graalvm.compiler.java.GraphBuilderPhase) InvocationPlugins(org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins) Plugins(org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins) StoreFieldNode(org.graalvm.compiler.nodes.java.StoreFieldNode) UnsupportedFeatureException(com.oracle.graal.pointsto.constraints.UnsupportedFeatureException) GraphBuilderConfiguration(org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration) DebugContext(org.graalvm.compiler.debug.DebugContext) LoadFieldNode(org.graalvm.compiler.nodes.java.LoadFieldNode) TrustedInterfaceTypePlugin(com.oracle.svm.core.graal.phases.TrustedInterfaceTypePlugin) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) ReturnNode(org.graalvm.compiler.nodes.ReturnNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) AccessFieldNode(org.graalvm.compiler.nodes.java.AccessFieldNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) CanonicalizerPhase(org.graalvm.compiler.phases.common.CanonicalizerPhase) InstanceOfNode(org.graalvm.compiler.nodes.java.InstanceOfNode) MethodHandlePlugin(org.graalvm.compiler.replacements.MethodHandlePlugin) WordOperationPlugin(org.graalvm.compiler.word.WordOperationPlugin)

Example 30 with ParameterNode

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

the class ReinterpretStampIntToFloatTest method run.

@Test
public void run() {
    ParameterNode param = new ParameterNode(0, StampPair.createSingle(inputStamp));
    ValueNode reinterpret = ReinterpretNode.create(JavaKind.Float, param, NodeView.DEFAULT);
    reinterpret.inferStamp();
    FloatStamp resultStamp = (FloatStamp) reinterpret.stamp(NodeView.DEFAULT);
    Assert.assertEquals(Float.SIZE, resultStamp.getBits());
    for (int input : interestingInts) {
        float result = Float.intBitsToFloat(input);
        if (inputStamp.contains(input) && !resultStamp.contains(result)) {
            Assert.fail(String.format("value 0x%x (%f) is in input stamp, but not in result stamp (%s)", input, result, resultStamp));
        }
    }
}
Also used : ParameterNode(org.graalvm.compiler.nodes.ParameterNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) FloatStamp(org.graalvm.compiler.core.common.type.FloatStamp) Test(org.junit.Test)

Aggregations

ParameterNode (org.graalvm.compiler.nodes.ParameterNode)46 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)19 ValueNode (org.graalvm.compiler.nodes.ValueNode)19 Node (org.graalvm.compiler.graph.Node)13 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)13 ReturnNode (org.graalvm.compiler.nodes.ReturnNode)13 Test (org.junit.Test)10 ResolvedJavaMethod (jdk.vm.ci.meta.ResolvedJavaMethod)9 ResolvedJavaType (jdk.vm.ci.meta.ResolvedJavaType)8 DebugContext (org.graalvm.compiler.debug.DebugContext)7 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)7 FrameState (org.graalvm.compiler.nodes.FrameState)7 InvokeWithExceptionNode (org.graalvm.compiler.nodes.InvokeWithExceptionNode)7 FixedNode (org.graalvm.compiler.nodes.FixedNode)6 CanonicalizerPhase (org.graalvm.compiler.phases.common.CanonicalizerPhase)6 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)5 InvokeNode (org.graalvm.compiler.nodes.InvokeNode)5 PhiNode (org.graalvm.compiler.nodes.PhiNode)5 ArrayList (java.util.ArrayList)4 JavaConstant (jdk.vm.ci.meta.JavaConstant)4