Search in sources :

Example 46 with ConstantNode

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

the class AheadOfTimeCompilationTest method testBoxedBoolean.

@Test
public void testBoxedBoolean() {
    StructuredGraph result = compile("getBoxedBoolean", false);
    assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count());
    assertDeepEquals(0, result.getNodes(PiNode.TYPE).count());
    assertDeepEquals(1, getConstantNodes(result).count());
    ConstantNode constant = getConstantNodes(result).first();
    assertDeepEquals(JavaKind.Object, constant.getStackKind());
    JavaConstant c = constant.asJavaConstant();
    Assert.assertEquals(getSnippetReflection().asObject(Boolean.class, c), Boolean.TRUE);
}
Also used : ConstantNode(org.graalvm.compiler.nodes.ConstantNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) JavaConstant(jdk.vm.ci.meta.JavaConstant) Test(org.junit.Test)

Example 47 with ConstantNode

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

the class AMD64HotSpotAddressLowering method tryOptimize.

private static void tryOptimize(OffsetAddressNode offsetAddress, LoopEx loop) {
    EconomicMap<Node, InductionVariable> ivs = loop.getInductionVariables();
    InductionVariable currentIV = ivs.get(offsetAddress.getOffset());
    while (currentIV != null) {
        if (!(currentIV instanceof DerivedInductionVariable)) {
            break;
        }
        ValueNode currentValue = currentIV.valueNode();
        if (currentValue.isDeleted()) {
            break;
        }
        if (currentValue instanceof ZeroExtendNode) {
            ZeroExtendNode zeroExtendNode = (ZeroExtendNode) currentValue;
            if (applicableToImplicitZeroExtend(zeroExtendNode)) {
                ValueNode input = zeroExtendNode.getValue();
                if (input instanceof AddNode) {
                    AddNode add = (AddNode) input;
                    if (add.getX().isConstant()) {
                        optimizeAdd(zeroExtendNode, (ConstantNode) add.getX(), add.getY(), loop);
                    } else if (add.getY().isConstant()) {
                        optimizeAdd(zeroExtendNode, (ConstantNode) add.getY(), add.getX(), loop);
                    }
                }
            }
        }
        currentIV = ((DerivedInductionVariable) currentIV).getBase();
    }
}
Also used : ConstantNode(org.graalvm.compiler.nodes.ConstantNode) AMD64AddressNode(org.graalvm.compiler.core.amd64.AMD64AddressNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) OffsetAddressNode(org.graalvm.compiler.nodes.memory.address.OffsetAddressNode) AddNode(org.graalvm.compiler.nodes.calc.AddNode) GraalHotSpotVMConfigNode(org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) ZeroExtendNode(org.graalvm.compiler.nodes.calc.ZeroExtendNode) CompressionNode(org.graalvm.compiler.nodes.CompressionNode) AddressNode(org.graalvm.compiler.nodes.memory.address.AddressNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Node(org.graalvm.compiler.graph.Node) PhiNode(org.graalvm.compiler.nodes.PhiNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) DerivedInductionVariable(org.graalvm.compiler.loop.DerivedInductionVariable) BasicInductionVariable(org.graalvm.compiler.loop.BasicInductionVariable) InductionVariable(org.graalvm.compiler.loop.InductionVariable) DerivedInductionVariable(org.graalvm.compiler.loop.DerivedInductionVariable) ZeroExtendNode(org.graalvm.compiler.nodes.calc.ZeroExtendNode) AddNode(org.graalvm.compiler.nodes.calc.AddNode)

Example 48 with ConstantNode

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

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

Example 50 with ConstantNode

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

Aggregations

ConstantNode (org.graalvm.compiler.nodes.ConstantNode)100 ValueNode (org.graalvm.compiler.nodes.ValueNode)46 JavaConstant (jdk.vm.ci.meta.JavaConstant)32 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)28 Stamp (org.graalvm.compiler.core.common.type.Stamp)23 Test (org.junit.Test)15 ResolvedJavaType (jdk.vm.ci.meta.ResolvedJavaType)14 Node (org.graalvm.compiler.graph.Node)14 ResolvedJavaMethod (jdk.vm.ci.meta.ResolvedJavaMethod)13 ParameterNode (org.graalvm.compiler.nodes.ParameterNode)13 PhiNode (org.graalvm.compiler.nodes.PhiNode)12 LogicNode (org.graalvm.compiler.nodes.LogicNode)11 IntegerStamp (org.graalvm.compiler.core.common.type.IntegerStamp)10 ArrayList (java.util.ArrayList)9 JavaKind (jdk.vm.ci.meta.JavaKind)9 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)9 Constant (jdk.vm.ci.meta.Constant)8 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)8 FixedGuardNode (org.graalvm.compiler.nodes.FixedGuardNode)7 LogicConstantNode (org.graalvm.compiler.nodes.LogicConstantNode)7