Search in sources :

Example 36 with JavaKind

use of jdk.vm.ci.meta.JavaKind in project graal by oracle.

the class PEReadEliminationClosure method processLoadIndexed.

private boolean processLoadIndexed(LoadIndexedNode load, PEReadEliminationBlockState state, GraphEffectList effects) {
    if (load.index().isConstant()) {
        int index = ((JavaConstant) load.index().asConstant()).asInt();
        // BALOAD (with elementKind being Byte) can be used to retrieve values from boolean
        // arrays.
        JavaKind elementKind = load.elementKind();
        if (elementKind == JavaKind.Byte) {
            elementKind = getElementKindFromStamp(load.array());
            if (elementKind == JavaKind.Illegal) {
                return false;
            }
        }
        LocationIdentity arrayLocation = NamedLocationIdentity.getArrayLocation(elementKind);
        return processLoad(load, load.array(), arrayLocation, index, elementKind, state, effects);
    }
    return false;
}
Also used : LocationIdentity(org.graalvm.word.LocationIdentity) FieldLocationIdentity(org.graalvm.compiler.nodes.FieldLocationIdentity) NamedLocationIdentity(org.graalvm.compiler.nodes.NamedLocationIdentity) JavaConstant(jdk.vm.ci.meta.JavaConstant) MemoryCheckpoint(org.graalvm.compiler.nodes.memory.MemoryCheckpoint) JavaKind(jdk.vm.ci.meta.JavaKind)

Example 37 with JavaKind

use of jdk.vm.ci.meta.JavaKind in project graal by oracle.

the class VirtualizerToolImpl method setVirtualEntry.

@Override
public boolean setVirtualEntry(VirtualObjectNode virtual, int index, ValueNode value, JavaKind theAccessKind, long offset) {
    ObjectState obj = state.getObjectState(virtual);
    assert obj.isVirtual() : "not virtual: " + obj;
    ValueNode newValue;
    JavaKind entryKind = virtual.entryKind(index);
    JavaKind accessKind = theAccessKind != null ? theAccessKind : entryKind;
    if (value == null) {
        newValue = null;
    } else {
        newValue = closure.getAliasAndResolve(state, value);
    }
    getDebug().log(DebugContext.DETAILED_LEVEL, "Setting entry %d in virtual object %s %s results in %s", index, virtual.getObjectId(), virtual, state.getObjectState(virtual.getObjectId()));
    ValueNode oldValue = getEntry(virtual, index);
    boolean canVirtualize = entryKind == accessKind || (entryKind == accessKind.getStackKind() && virtual instanceof VirtualInstanceNode);
    if (!canVirtualize) {
        if (entryKind == JavaKind.Long && oldValue.getStackKind() == newValue.getStackKind() && oldValue.getStackKind().isPrimitive()) {
            /*
                 * Special case: If the entryKind is long, allow arbitrary kinds as long as a value
                 * of the same kind is already there. This can only happen if some other node
                 * initialized the entry with a value of a different kind. One example where this
                 * happens is the Truffle NewFrameNode.
                 */
            getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s with primitive of kind %s in long entry ", current, oldValue.getStackKind());
            canVirtualize = true;
        } else if (entryKind == JavaKind.Int && (accessKind == JavaKind.Long || accessKind == JavaKind.Double) && offset % 8 == 0) {
            /*
                 * Special case: Allow storing a single long or double value into two consecutive
                 * int slots.
                 */
            int nextIndex = virtual.entryIndexForOffset(getArrayOffsetProvider(), offset + 4, JavaKind.Int);
            if (nextIndex != -1) {
                canVirtualize = true;
                assert nextIndex == index + 1 : "expected to be sequential";
                getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s for double word stored in two ints", current);
            }
        }
    }
    if (canVirtualize) {
        getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s for entryKind %s and access kind %s", current, entryKind, accessKind);
        state.setEntry(virtual.getObjectId(), index, newValue);
        if (entryKind == JavaKind.Int) {
            if (accessKind.needsTwoSlots()) {
                // Storing double word value two int slots
                assert virtual.entryKind(index + 1) == JavaKind.Int;
                state.setEntry(virtual.getObjectId(), index + 1, getIllegalConstant());
            } else if (oldValue.getStackKind() == JavaKind.Double || oldValue.getStackKind() == JavaKind.Long) {
                // Splitting double word constant by storing over it with an int
                getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s producing second half of double word value %s", current, oldValue);
                ValueNode secondHalf = UnpackEndianHalfNode.create(oldValue, false, NodeView.DEFAULT);
                addNode(secondHalf);
                state.setEntry(virtual.getObjectId(), index + 1, secondHalf);
            }
        }
        if (oldValue.isConstant() && oldValue.asConstant().equals(JavaConstant.forIllegal())) {
            // Storing into second half of double, so replace previous value
            ValueNode previous = getEntry(virtual, index - 1);
            getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s producing first half of double word value %s", current, previous);
            ValueNode firstHalf = UnpackEndianHalfNode.create(previous, true, NodeView.DEFAULT);
            addNode(firstHalf);
            state.setEntry(virtual.getObjectId(), index - 1, firstHalf);
        }
        return true;
    }
    // Should only occur if there are mismatches between the entry and access kind
    assert entryKind != accessKind;
    return false;
}
Also used : ValueNode(org.graalvm.compiler.nodes.ValueNode) VirtualInstanceNode(org.graalvm.compiler.nodes.virtual.VirtualInstanceNode) JavaKind(jdk.vm.ci.meta.JavaKind)

Example 38 with JavaKind

use of jdk.vm.ci.meta.JavaKind 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 39 with JavaKind

use of jdk.vm.ci.meta.JavaKind in project graal by oracle.

the class JNIJavaCallWrapperMethod method createSignature.

private JNISignature createSignature(MetaAccessProvider metaAccess) {
    ResolvedJavaType objectHandle = metaAccess.lookupJavaType(JNIObjectHandle.class);
    List<JavaType> args = new ArrayList<>();
    args.add(metaAccess.lookupJavaType(JNIEnvironment.class));
    // this (instance method) or class (static method)
    args.add(objectHandle);
    if (nonVirtual) {
        // class of implementation to invoke
        args.add(objectHandle);
    }
    args.add(metaAccess.lookupJavaType(JNIMethodId.class));
    Signature targetSignature = targetMethod.getSignature();
    if (callVariant == CallVariant.VARARGS) {
        for (JavaType targetArg : targetSignature.toParameterTypes(null)) {
            JavaKind kind = targetArg.getJavaKind();
            if (kind.isObject()) {
                args.add(objectHandle);
            } else if (kind == JavaKind.Float) {
                // C varargs promote float to double
                args.add(metaAccess.lookupJavaType(JavaKind.Double.toJavaClass()));
            } else {
                args.add(targetArg);
            }
        }
    } else if (callVariant == CallVariant.ARRAY) {
        // const jvalue *
        args.add(metaAccess.lookupJavaType(JNIValue.class));
    } else if (callVariant == CallVariant.VA_LIST) {
        // va_list (a pointer of some kind)
        args.add(metaAccess.lookupJavaType(WordBase.class));
    } else {
        throw VMError.shouldNotReachHere();
    }
    JavaType returnType = targetSignature.getReturnType(null);
    if (returnType.getJavaKind().isObject() || targetMethod.isConstructor()) {
        // Constructor: returns `this` to implement NewObject
        returnType = objectHandle;
    }
    return new JNISignature(args, returnType);
}
Also used : ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) JavaType(jdk.vm.ci.meta.JavaType) JNIEnvironment(com.oracle.svm.jni.nativeapi.JNIEnvironment) Signature(jdk.vm.ci.meta.Signature) ArrayList(java.util.ArrayList) WordBase(org.graalvm.word.WordBase) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) JNIMethodId(com.oracle.svm.jni.nativeapi.JNIMethodId) JavaKind(jdk.vm.ci.meta.JavaKind)

Example 40 with JavaKind

use of jdk.vm.ci.meta.JavaKind 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

JavaKind (jdk.vm.ci.meta.JavaKind)90 ValueNode (org.graalvm.compiler.nodes.ValueNode)44 ResolvedJavaType (jdk.vm.ci.meta.ResolvedJavaType)24 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)17 ResolvedJavaMethod (jdk.vm.ci.meta.ResolvedJavaMethod)16 AddressNode (org.graalvm.compiler.nodes.memory.address.AddressNode)13 OffsetAddressNode (org.graalvm.compiler.nodes.memory.address.OffsetAddressNode)12 JavaType (jdk.vm.ci.meta.JavaType)11 Stamp (org.graalvm.compiler.core.common.type.Stamp)10 LocationIdentity (org.graalvm.word.LocationIdentity)10 ArrayList (java.util.ArrayList)9 JavaConstant (jdk.vm.ci.meta.JavaConstant)9 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)8 FrameState (org.graalvm.compiler.nodes.FrameState)8 GraphBuilderContext (org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext)8 Signature (jdk.vm.ci.meta.Signature)7 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)7 ObjectLayout (com.oracle.svm.core.config.ObjectLayout)6 ObjectStamp (org.graalvm.compiler.core.common.type.ObjectStamp)6 InvokeWithExceptionNode (org.graalvm.compiler.nodes.InvokeWithExceptionNode)6