Search in sources :

Example 21 with AnalysisObject

use of com.oracle.graal.pointsto.flow.context.object.AnalysisObject in project graal by oracle.

the class TypeStateUtils method arraysIntersection.

/**
 * Returns a list containing the intersection of the two object arrays.
 */
private static AnalysisObject[] arraysIntersection(BigBang bb, AnalysisObject[] a1, AnalysisObject[] a2) {
    assert a1.length <= a2.length : "Intersection is commutative, must call it with a1 being the shorter array";
    if (a1 == a2) {
        return a1;
    }
    /* Speculate that a1 contains no more elements than a2, i.e., the result is a1. */
    int idx1 = 0;
    int idx2 = 0;
    while (idx2 < a2.length) {
        AnalysisObject o1 = a1[idx1];
        AnalysisObject o2 = a2[idx2];
        if (o2.getId() < o1.getId()) {
            idx2++;
        } else if (o1.equals(o2)) {
            /* If the objects are equal continue with speculation. */
            idx1++;
            idx2++;
            if (idx1 == a1.length) {
                /*
                     * The speculation succeeded: we walked down the whole a1 array and it contained
                     * no more elements than a2.
                     */
                return a1;
            }
        } else {
            /* The speculation failed. */
            break;
        }
    }
    List<AnalysisObject> rList = new ArrayList<>(a1.length);
    /* Add the beginning of the a1 list that we already walked above. */
    rList.addAll(Arrays.asList(a1).subList(0, idx1));
    while (idx1 < a1.length && idx2 < a2.length) {
        AnalysisObject o1 = a1[idx1];
        AnalysisObject o2 = a2[idx2];
        if (o1.equals(o2)) {
            rList.add(o1);
            idx1++;
            idx2++;
        } else {
            // keep the list sorted by the id
            assert o1.getId() != o2.getId();
            if (o1.getId() < o2.getId()) {
                idx1++;
            } else {
                idx2++;
            }
        }
    }
    /* For intersection the result must be smaller than the operands. */
    assert rList.size() <= a1.length && rList.size() <= a2.length;
    /*
         * If the LimitObjectArrayLength is enabled then the result MUST be smaller than
         * MaxObjectSetSize.
         */
    assert !PointstoOptions.LimitObjectArrayLength.getValue(bb.getOptions()) || rList.size() <= PointstoOptions.MaxObjectSetSize.getValue(bb.getOptions());
    if (rList.size() == 0) {
        return AnalysisObject.EMPTY_ARRAY;
    } else {
        AnalysisObject[] result = rList.toArray(new AnalysisObject[rList.size()]);
        assert !Arrays.equals(result, a1) && !Arrays.equals(result, a2);
        return result;
    }
}
Also used : AnalysisObject(com.oracle.graal.pointsto.flow.context.object.AnalysisObject) ArrayList(java.util.ArrayList)

Example 22 with AnalysisObject

use of com.oracle.graal.pointsto.flow.context.object.AnalysisObject in project graal by oracle.

the class ArrayCopyTypeFlow method onObservedUpdate.

@Override
public void onObservedUpdate(BigBang bb) {
    assert this.isClone();
    /*
         * Both the source and the destination register this flow as an observer and notify it when
         * either of them is updated. When either the source or the destination elements change the
         * element flows from source are passed to destination.
         */
    TypeState srcArrayState = srcArrayFlow.getState();
    TypeState dstArrayState = dstArrayFlow.getState();
    /*
         * The source and destination array can have reference types which, although must be
         * compatible, can be different.
         */
    for (AnalysisObject srcArrayObject : srcArrayState.objects()) {
        if (!srcArrayObject.type().isArray()) {
            /*
                 * Ignore non-array type. Sometimes the analysis cannot filter out non-array types
                 * flowing into array copy, however this will fail at runtime.
                 */
            continue;
        }
        assert srcArrayObject.type().isArray();
        if (srcArrayObject.isPrimitiveArray() || srcArrayObject.isEmptyObjectArrayConstant(bb)) {
            /* Nothing to read from a primitive array or an empty array constant. */
            continue;
        }
        ArrayElementsTypeFlow srcArrayElementsFlow = srcArrayObject.getArrayElementsFlow(bb, false);
        for (AnalysisObject dstArrayObject : dstArrayState.objects()) {
            if (!dstArrayObject.type().isArray()) {
                /* Ignore non-array type. */
                continue;
            }
            assert dstArrayObject.type().isArray();
            if (dstArrayObject.isPrimitiveArray() || dstArrayObject.isEmptyObjectArrayConstant(bb)) {
                /* Cannot write to a primitive array or an empty array constant. */
                continue;
            }
            /*
                 * As far as the ArrayCopyTypeFlow is concerned the source and destination types can
                 * be compatible or not, where compatibility is defined as: the component of the
                 * source array can be converted to the component type of the destination array by
                 * assignment conversion. System.arraycopy() semantics doesn't check the
                 * compatibility of the source and destination arrays, it instead relies on runtime
                 * checks of the compatibility of the copied objects and the destination array. For
                 * example System.arraycopy() can copy from an Object[] to SomeOtherObject[]. In
                 * this case a check dstArrayObject.type().isAssignableFrom(srcArrayObject.type()
                 * would fail but it is actually a valid use. That's why ArrayElementsTypeFlow will
                 * test each individual copied object for compatibility with the defined type of the
                 * destination array and filter out those not assignable. From System.arraycopy()
                 * javadoc: "...if any actual component of the source array from position srcPos
                 * through srcPos+length-1 cannot be converted to the component type of the
                 * destination array by assignment conversion, an ArrayStoreException is thrown."
                 */
            ArrayElementsTypeFlow dstArrayElementsFlow = dstArrayObject.getArrayElementsFlow(bb, true);
            srcArrayElementsFlow.addUse(bb, dstArrayElementsFlow);
        }
    }
}
Also used : AnalysisObject(com.oracle.graal.pointsto.flow.context.object.AnalysisObject) TypeState(com.oracle.graal.pointsto.typestate.TypeState)

Example 23 with AnalysisObject

use of com.oracle.graal.pointsto.flow.context.object.AnalysisObject in project graal by oracle.

the class AnalysisObjectScanner method forNonNullFieldValue.

@Override
public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue) {
    AnalysisType fieldType = bb.getMetaAccess().lookupJavaType(bb.getSnippetReflectionProvider().asObject(Object.class, fieldValue).getClass());
    assert fieldType.isInstantiated();
    if (bb.getAllInstantiatedTypeFlow().getState().containsType(fieldType)) {
        /* Add the constant value object to the field's type flow. */
        FieldTypeFlow fieldTypeFlow = getFieldTypeFlow(field, receiver);
        AnalysisObject constantObject = bb.analysisPolicy().createConstantObject(bb, fieldValue, fieldType);
        if (!fieldTypeFlow.getState().isUnknown() && !fieldTypeFlow.getState().containsObject(constantObject)) {
            /* Add the new constant to the field's flow state. */
            TypeState constantTypeState = TypeState.forNonNullObject(bb, constantObject);
            fieldTypeFlow.addState(bb, constantTypeState);
        }
    }
}
Also used : AnalysisType(com.oracle.graal.pointsto.meta.AnalysisType) AnalysisObject(com.oracle.graal.pointsto.flow.context.object.AnalysisObject) FieldTypeFlow(com.oracle.graal.pointsto.flow.FieldTypeFlow) TypeState(com.oracle.graal.pointsto.typestate.TypeState)

Example 24 with AnalysisObject

use of com.oracle.graal.pointsto.flow.context.object.AnalysisObject in project graal by oracle.

the class AnalysisObjectScanner method getFieldTypeFlow.

/**
 * Get the field type flow give a receiver.
 */
private FieldTypeFlow getFieldTypeFlow(AnalysisField field, JavaConstant receiver) {
    /* The field type flow is used to track the constant field value. */
    if (field.isStatic()) {
        /* If the field is static it comes from the originalRoots. */
        return field.getStaticFieldFlow();
    } else {
        /*
             * The field comes from a constant scan, thus it's type flow is mapped to the unique
             * constant object.
             */
        AnalysisType receiverType = bb.getMetaAccess().lookupJavaType(bb.getSnippetReflectionProvider().asObject(Object.class, receiver).getClass());
        AnalysisObject constantReceiverObj = bb.analysisPolicy().createConstantObject(bb, receiver, receiverType);
        return constantReceiverObj.getInstanceFieldFlow(bb, field, true);
    }
}
Also used : AnalysisType(com.oracle.graal.pointsto.meta.AnalysisType) AnalysisObject(com.oracle.graal.pointsto.flow.context.object.AnalysisObject)

Aggregations

AnalysisObject (com.oracle.graal.pointsto.flow.context.object.AnalysisObject)24 BitSet (java.util.BitSet)8 TypeState (com.oracle.graal.pointsto.typestate.TypeState)5 AnalysisType (com.oracle.graal.pointsto.meta.AnalysisType)4 AnalysisContext (com.oracle.graal.pointsto.flow.context.AnalysisContext)2 Range (com.oracle.graal.pointsto.typestate.MultiTypeState.Range)2 ArrayElementsTypeFlow (com.oracle.graal.pointsto.flow.ArrayElementsTypeFlow)1 FieldTypeFlow (com.oracle.graal.pointsto.flow.FieldTypeFlow)1 ConstantContextSensitiveObject (com.oracle.graal.pointsto.flow.context.object.ConstantContextSensitiveObject)1 AnalysisField (com.oracle.graal.pointsto.meta.AnalysisField)1 ArrayList (java.util.ArrayList)1 PrimitiveConstant (jdk.vm.ci.meta.PrimitiveConstant)1 MethodCallTargetNode (org.graalvm.compiler.nodes.java.MethodCallTargetNode)1