Search in sources :

Example 26 with ResolvedJavaField

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

the class ComputedValueField method computeAtomicFieldUpdaterOffset.

private JavaConstant computeAtomicFieldUpdaterOffset(JavaConstant receiver) {
    assert !Modifier.isStatic(original.getModifiers());
    assert receiver.isNonNull();
    /*
         * Explanation: java.util.concurrent is full of objects and classes that cache the offset of
         * particular fields in the JDK. Here, Atomic<X>FieldUpdater implementation objects cache
         * the offset of some specified field. Which field? Oh...only Doug Lea knows that. We have
         * to search the declaring class for a field that has the same "unsafe" offset as the cached
         * offset in this atomic updater object.
         */
    ResolvedJavaField tclassField = findField(original.getDeclaringClass(), "tclass");
    SnippetReflectionProvider originalSnippetReflection = GraalAccess.getOriginalSnippetReflection();
    Class<?> tclass = originalSnippetReflection.asObject(Class.class, ReadableJavaField.readFieldValue(GraalAccess.getOriginalProviders().getConstantReflection(), tclassField, receiver));
    return translateFieldOffset(receiver, tclass);
}
Also used : SnippetReflectionProvider(org.graalvm.compiler.api.replacements.SnippetReflectionProvider) ResolvedJavaField(jdk.vm.ci.meta.ResolvedJavaField)

Example 27 with ResolvedJavaField

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

the class UnsafeAutomaticSubstitutionProcessor method processUnsafeArrayIndexScaleInvoke.

/**
 * Process call to {@link sun.misc.Unsafe#arrayIndexScale(Class)}. The matching logic below
 * applies to the following code pattern:
 *
 * <code> static final long byteArrayIndexScale = Unsafe.getUnsafe().arrayIndexScale(byte[].class); </code>
 */
private void processUnsafeArrayIndexScaleInvoke(ResolvedJavaType type, Invoke unsafeArrayIndexScale, StructuredGraph clinitGraph) {
    SnippetReflectionProvider snippetReflectionProvider = GraalAccess.getOriginalSnippetReflection();
    List<String> unsuccessfulReasons = new ArrayList<>();
    Class<?> arrayClass = null;
    ValueNode arrayClassArgument = unsafeArrayIndexScale.callTarget().arguments().get(1);
    if (arrayClassArgument.isJavaConstant()) {
        arrayClass = snippetReflectionProvider.asObject(Class.class, arrayClassArgument.asJavaConstant());
    } else {
        unsuccessfulReasons.add("The first argument of the call to Unsafe.arrayIndexScale() is not a constant.");
    }
    /*
         * If the value returned by the call to Unsafe.unsafeArrayIndexScale() is stored into a
         * field then that must be the offset field.
         */
    ResolvedJavaField indexScaleField = extractValueStoreField(unsafeArrayIndexScale.asNode(), unsuccessfulReasons);
    boolean indexScaleComputed = false;
    boolean indexShiftComputed = false;
    if (arrayClass != null) {
        if (indexScaleField != null) {
            Class<?> finalArrayClass = arrayClass;
            Supplier<ComputedValueField> supplier = () -> new ComputedValueField(indexScaleField, null, Kind.ArrayIndexScale, finalArrayClass, null, true);
            if (tryAutomaticRecomputation(indexScaleField, Kind.ArrayIndexScale, supplier)) {
                reportSuccessfulAutomaticRecomputation(Kind.ArrayIndexScale, indexScaleField, arrayClass.getCanonicalName());
                indexScaleComputed = true;
                /* Try substitution for the array index shift computation if present. */
                indexShiftComputed = processArrayIndexShiftFromField(type, indexScaleField, arrayClass, clinitGraph);
            }
        } else {
            /*
                 * The index scale is not stored into a field, it might be used to compute the index
                 * shift.
                 */
            indexShiftComputed = processArrayIndexShiftFromLocal(type, unsafeArrayIndexScale, arrayClass);
        }
    }
    if (!indexScaleComputed && !indexShiftComputed) {
        reportUnsuccessfulAutomaticRecomputation(type, unsafeArrayIndexScale, Kind.ArrayIndexScale, unsuccessfulReasons);
    }
}
Also used : SnippetReflectionProvider(org.graalvm.compiler.api.replacements.SnippetReflectionProvider) ArrayList(java.util.ArrayList) ValueNode(org.graalvm.compiler.nodes.ValueNode) ResolvedJavaField(jdk.vm.ci.meta.ResolvedJavaField)

Example 28 with ResolvedJavaField

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

the class UnsafeAutomaticSubstitutionProcessor method processArrayIndexShift.

/**
 * Try to compute the arrayIndexShift. Return true if successful, false otherwise.
 */
private boolean processArrayIndexShift(ResolvedJavaType type, Class<?> arrayClass, ValueNode indexScaleValue, boolean silentFailure) {
    NodeIterable<MethodCallTargetNode> loadMethodCallTargetUsages = indexScaleValue.usages().filter(MethodCallTargetNode.class);
    for (MethodCallTargetNode methodCallTarget : loadMethodCallTargetUsages) {
        /* Iterate over all the calls that use the index scale value. */
        if (isInvokeTo(methodCallTarget.invoke(), integerNumberOfLeadingZerosMethod)) {
            /*
                 * Found a call to Integer.numberOfLeadingZeros(int) that uses the array index scale
                 * field. Check if it is used to calculate the array index shift, i.e., log2 of the
                 * array index scale.
                 */
            ResolvedJavaField indexShiftField = null;
            List<String> unsuccessfulReasons = new ArrayList<>();
            Invoke numberOfLeadingZerosInvoke = methodCallTarget.invoke();
            NodeIterable<SubNode> numberOfLeadingZerosInvokeSubUsages = numberOfLeadingZerosInvoke.asNode().usages().filter(SubNode.class);
            if (numberOfLeadingZerosInvokeSubUsages.count() == 1) {
                /*
                     * Found the SubNode. Determine if it computes the array index shift. If so find
                     * the field where the value is stored.
                     */
                SubNode subNode = numberOfLeadingZerosInvokeSubUsages.first();
                if (subNodeComputesLog2(subNode, numberOfLeadingZerosInvoke)) {
                    indexShiftField = extractValueStoreField(subNode, unsuccessfulReasons);
                } else {
                    unsuccessfulReasons.add("The index array scale value provided by " + indexScaleValue + " is not used to calculate the array index shift.");
                }
            } else {
                unsuccessfulReasons.add("The call to " + methodCallTarget.targetMethod().format("%H.%n(%p)") + " has multiple uses.");
            }
            if (indexShiftField != null) {
                ResolvedJavaField finalIndexShiftField = indexShiftField;
                Supplier<ComputedValueField> supplier = () -> new ComputedValueField(finalIndexShiftField, null, Kind.ArrayIndexShift, arrayClass, null, true);
                if (tryAutomaticRecomputation(indexShiftField, Kind.ArrayIndexShift, supplier)) {
                    reportSuccessfulAutomaticRecomputation(Kind.ArrayIndexShift, indexShiftField, arrayClass.getCanonicalName());
                    return true;
                }
            } else {
                if (!silentFailure) {
                    reportUnsuccessfulAutomaticRecomputation(type, numberOfLeadingZerosInvoke, Kind.ArrayIndexShift, unsuccessfulReasons);
                }
            }
        }
    }
    return false;
}
Also used : MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) SubNode(org.graalvm.compiler.nodes.calc.SubNode) ArrayList(java.util.ArrayList) ResolvedJavaField(jdk.vm.ci.meta.ResolvedJavaField) Invoke(org.graalvm.compiler.nodes.Invoke)

Example 29 with ResolvedJavaField

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

the class UnsafeAutomaticSubstitutionProcessor method processUnsafeObjectFieldOffsetInvoke.

/**
 * Process call to {@link sun.misc.Unsafe#objectFieldOffset(Field)}. The matching logic below
 * applies to the following code pattern:
 *
 * <code> static final long fieldOffset = Unsafe.getUnsafe().objectFieldOffset(X.class.getDeclaredField("f")); </code>
 */
private void processUnsafeObjectFieldOffsetInvoke(ResolvedJavaType type, Invoke unsafeObjectFieldOffsetInvoke) {
    SnippetReflectionProvider snippetReflectionProvider = GraalAccess.getOriginalSnippetReflection();
    List<String> unsuccessfulReasons = new ArrayList<>();
    Class<?> targetFieldHolder = null;
    String targetFieldName = null;
    ValueNode fieldArgument = unsafeObjectFieldOffsetInvoke.callTarget().arguments().get(1);
    if (fieldArgument instanceof Invoke && isInvokeTo((Invoke) fieldArgument, classGetDeclaredFieldMethod)) {
        Invoke getDeclaredFieldInvoke = (Invoke) fieldArgument;
        /*
             * If the first argument of Unsafe.objectFieldOffset() is a call to
             * Class.getDeclaredField() and the arguments of Class.getDeclaredField(), i.e., the
             * class and the field name, are constants then unwrap them.
             */
        ValueNode holderClassNode = getDeclaredFieldInvoke.callTarget().arguments().get(0);
        if (holderClassNode.isJavaConstant()) {
            targetFieldHolder = snippetReflectionProvider.asObject(Class.class, holderClassNode.asJavaConstant());
        } else {
            unsuccessfulReasons.add("The receiver of the call to Class.getDeclaredField(), i.e., the field holder class, is not a constant.");
        }
        ValueNode fieldNameNode = getDeclaredFieldInvoke.callTarget().arguments().get(1);
        if (fieldNameNode.isJavaConstant()) {
            targetFieldName = snippetReflectionProvider.asObject(String.class, fieldNameNode.asJavaConstant());
        } else {
            unsuccessfulReasons.add("The first argument of the call to Class.getDeclaredField(), i.e., the field name, is not a constant.");
        }
    } else {
        unsuccessfulReasons.add("The first argument of Unsafe.objectFieldOffset() is not a call to Class.getDeclaredField()");
    }
    /*
         * If the value returned by the call to Unsafe.objectFieldOffset() is stored into a field
         * then that must be the offset field.
         */
    ResolvedJavaField offsetField = extractValueStoreField(unsafeObjectFieldOffsetInvoke.asNode(), unsuccessfulReasons);
    /*
         * If the target field holder and name, and the offset field were found try to register a
         * substitution.
         */
    if (targetFieldHolder != null && targetFieldName != null && offsetField != null) {
        Class<?> finalTargetFieldHolder = targetFieldHolder;
        String finalTargetFieldName = targetFieldName;
        Supplier<ComputedValueField> supplier = () -> new ComputedValueField(offsetField, null, Kind.FieldOffset, finalTargetFieldHolder, finalTargetFieldName, false);
        if (tryAutomaticRecomputation(offsetField, Kind.FieldOffset, supplier)) {
            reportSuccessfulAutomaticRecomputation(Kind.FieldOffset, offsetField, targetFieldHolder.getName() + "." + targetFieldName);
        }
    } else {
        reportUnsuccessfulAutomaticRecomputation(type, unsafeObjectFieldOffsetInvoke, Kind.FieldOffset, unsuccessfulReasons);
    }
}
Also used : SnippetReflectionProvider(org.graalvm.compiler.api.replacements.SnippetReflectionProvider) ArrayList(java.util.ArrayList) ValueNode(org.graalvm.compiler.nodes.ValueNode) Invoke(org.graalvm.compiler.nodes.Invoke) ResolvedJavaField(jdk.vm.ci.meta.ResolvedJavaField)

Example 30 with ResolvedJavaField

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

the class UnsafeAutomaticSubstitutionProcessor method extractValueStoreField.

/**
 * If the value produced by valueNode is stored into a static final field then that field is
 * returned. If the field is either not static or not final the method returns null and the
 * reason is recorded in the unsuccessfulReasons parameter.
 */
private static ResolvedJavaField extractValueStoreField(ValueNode valueNode, List<String> unsuccessfulReasons) {
    ResolvedJavaField offsetField = null;
    NodeIterable<Node> valueNodeUsages = valueNode.usages();
    NodeIterable<StoreFieldNode> valueNodeStoreFieldUsages = valueNodeUsages.filter(StoreFieldNode.class);
    NodeIterable<SignExtendNode> valueNodeSignExtendUsages = valueNodeUsages.filter(SignExtendNode.class);
    if (valueNodeStoreFieldUsages.count() == 1) {
        offsetField = valueNodeStoreFieldUsages.first().field();
    } else if (valueNodeSignExtendUsages.count() == 1) {
        SignExtendNode signExtendNode = valueNodeSignExtendUsages.first();
        NodeIterable<StoreFieldNode> signExtendFieldStoreUsages = signExtendNode.usages().filter(StoreFieldNode.class);
        if (signExtendFieldStoreUsages.count() == 1) {
            offsetField = signExtendFieldStoreUsages.first().field();
        }
    }
    if (offsetField != null) {
        if (offsetField.isStatic() && offsetField.isFinal()) {
            return offsetField;
        } else {
            if (!offsetField.isStatic()) {
                unsuccessfulReasons.add("The offset field " + offsetField.format("%H.%n") + " is not static.");
            }
            if (!offsetField.isFinal()) {
                unsuccessfulReasons.add("The offset field " + offsetField.format("%H.%n") + " is not final.");
            }
        }
    } else {
        String producer;
        String operation;
        if (valueNode instanceof Invoke) {
            Invoke invokeNode = (Invoke) valueNode;
            producer = "call to " + invokeNode.callTarget().targetMethod().format("%H.%n(%p)");
            operation = "call";
        } else if (valueNode instanceof SubNode) {
            producer = "subtraction operation " + valueNode;
            operation = "subtraction";
        } else {
            throw VMError.shouldNotReachHere();
        }
        String message = "Could not determine the field where the value produced by the " + producer + " is stored. The " + operation + " is not directly followed by a field store or by a sign extend node followed directly by a field store. ";
        unsuccessfulReasons.add(message);
    }
    return null;
}
Also used : StoreFieldNode(org.graalvm.compiler.nodes.java.StoreFieldNode) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) NodeIterable(org.graalvm.compiler.graph.iterators.NodeIterable) SubNode(org.graalvm.compiler.nodes.calc.SubNode) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) LoadFieldNode(org.graalvm.compiler.nodes.java.LoadFieldNode) SubNode(org.graalvm.compiler.nodes.calc.SubNode) StoreFieldNode(org.graalvm.compiler.nodes.java.StoreFieldNode) Node(org.graalvm.compiler.graph.Node) ResolvedJavaField(jdk.vm.ci.meta.ResolvedJavaField) Invoke(org.graalvm.compiler.nodes.Invoke)

Aggregations

ResolvedJavaField (jdk.vm.ci.meta.ResolvedJavaField)45 ValueNode (org.graalvm.compiler.nodes.ValueNode)16 ResolvedJavaMethod (jdk.vm.ci.meta.ResolvedJavaMethod)10 ResolvedJavaType (jdk.vm.ci.meta.ResolvedJavaType)10 ArrayList (java.util.ArrayList)7 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)6 AnalysisField (com.oracle.graal.pointsto.meta.AnalysisField)4 Field (java.lang.reflect.Field)4 JavaKind (jdk.vm.ci.meta.JavaKind)4 Invoke (org.graalvm.compiler.nodes.Invoke)4 OffsetAddressNode (org.graalvm.compiler.nodes.memory.address.OffsetAddressNode)4 SnippetReflectionProvider (org.graalvm.compiler.api.replacements.SnippetReflectionProvider)3 DebugCloseable (org.graalvm.compiler.debug.DebugCloseable)3 NodePlugin (org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin)3 LoadFieldNode (org.graalvm.compiler.nodes.java.LoadFieldNode)3 LocationIdentity (org.graalvm.word.LocationIdentity)3 Delete (com.oracle.svm.core.annotate.Delete)2 Method (java.lang.reflect.Method)2 JavaField (jdk.vm.ci.meta.JavaField)2 MetaAccessProvider (jdk.vm.ci.meta.MetaAccessProvider)2