Search in sources :

Example 11 with AnalysisObject

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

the class UnknownTypeState method doUnion2.

private static TypeState doUnion2(BigBang bb, MultiTypeState s1, MultiTypeState s2, boolean resultCanBeNull, int startId1, int startId2) {
    int idx1 = startId1;
    int idx2 = startId2;
    try (UnsafeArrayListClosable<AnalysisObject> resultObjectsClosable = getTLArrayList(doUnion2TL, s1.objects.length + s2.objects.length)) {
        UnsafeArrayList<AnalysisObject> resultObjects = resultObjectsClosable.list;
        /* Add the beginning of the s1 list that we already walked above. */
        AnalysisObject[] objects = s1.objects;
        resultObjects.addAll(objects, 0, idx1);
        /* Create the union of the overlapping sections of the s1 and s2. */
        try (UnsafeArrayListClosable<AnalysisObject> tlUnionObjectsClosable = getTLArrayList(doUnion2ObjectsTL, s1.objects.length + s2.objects.length)) {
            UnsafeArrayList<AnalysisObject> unionObjects = tlUnionObjectsClosable.list;
            while (idx1 < s1.objects.length && idx2 < s2.objects.length) {
                AnalysisObject o1 = s1.objects[idx1];
                AnalysisObject o2 = s2.objects[idx2];
                if (bb.analysisPolicy().isSummaryObject(o1) && o1.type().equals(o2.type())) {
                    unionObjects.add(o1);
                    idx1++;
                    /* Skip over s2 objects of this type while marking them as merged. */
                    while (idx2 < s2.objects.length && s2.objects[idx2].type().equals(o1.type())) {
                        bb.analysisPolicy().noteMerge(bb, s2.objects[idx2]);
                        idx2++;
                    }
                } else if (bb.analysisPolicy().isSummaryObject(o2) && o1.type().equals(o2.type())) {
                    unionObjects.add(o2);
                    idx2++;
                    /* Skip over s1 objects of this type while marking them as merged. */
                    while (idx1 < s1.objects.length && s1.objects[idx1].type().equals(o2.type())) {
                        bb.analysisPolicy().noteMerge(bb, s1.objects[idx1]);
                        idx1++;
                    }
                } else if (o1.getId() < o2.getId()) {
                    unionObjects.add(o1);
                    idx1++;
                } else if (o1.getId() > o2.getId()) {
                    unionObjects.add(o2);
                    idx2++;
                } else {
                    assert o1.equals(o2);
                    unionObjects.add(o1);
                    idx1++;
                    idx2++;
                }
            }
            /*
                 * Check if the union of objects of a type in the overlapping section reached the
                 * limit. The limit, bb.options().maxObjectSetSize(), has a minimum value of 1.
                 */
            if (PointstoOptions.LimitObjectArrayLength.getValue(bb.getOptions()) && unionObjects.size() > PointstoOptions.MaxObjectSetSize.getValue(bb.getOptions())) {
                int idxStart = 0;
                int idxEnd = 0;
                while (idxEnd < unionObjects.size()) {
                    AnalysisObject oStart = unionObjects.get(idxStart);
                    /* While types are equal and the end is not reached, advance idxEnd. */
                    while (idxEnd < unionObjects.size() && oStart.equals(unionObjects.get(idxEnd))) {
                        idxEnd = idxEnd + 1;
                    }
                    /*
                         * Process the type change or, if idxEnd reached the end, process the last
                         * stride
                         */
                    int size = idxEnd - idxStart;
                    if (size > PointstoOptions.MaxObjectSetSize.getValue(bb.getOptions())) {
                        /*
                             * Object count exceeds the limit. Mark the objects in the stride as
                             * merged.
                             */
                        for (int i = idxStart; i < idxEnd; i += 1) {
                            bb.analysisPolicy().noteMerge(bb, unionObjects.get(i));
                        }
                        /* Add the context insensitive object in the result list. */
                        resultObjects.add(oStart.type().getContextInsensitiveAnalysisObject());
                    } else {
                        /* Object count is within the limit, add them to the result. */
                        resultObjects.addAll(unionObjects.elementData, idxStart, idxEnd);
                    }
                    idxStart = idxEnd;
                }
            } else {
                resultObjects.addAll(unionObjects.elementData, 0, unionObjects.size);
            }
        }
        /*
             * Add the leftover objects in the result list.
             *
             * Arrays.asList(a).subList(from, to) first creates a list wrapper over the array then
             * it creates a view of a portion of the list, thus it only allocates the list and
             * sub-list wrappers. Then ArrayList.addAll() calls System.arraycopy() which should be
             * more efficient than copying one element at a time.
             */
        if (idx1 < s1.objects.length) {
            resultObjects.addAll(s1.objects, idx1, s1.objects.length);
        } else if (idx2 < s2.objects.length) {
            resultObjects.addAll(s2.objects, idx2, s2.objects.length);
        }
        assert resultObjects.size() > 1 : "The result state of a (Multi U Multi) operation must have at least 2 objects";
        /* Logical OR the type bit sets. */
        BitSet resultTypesBitSet = TypeStateUtils.or(s1.typesBitSet, s2.typesBitSet);
        int properties = bb.analysisPolicy().makePopertiesForUnion(s1, s2);
        MultiTypeState result = new MultiTypeState(bb, resultCanBeNull, properties, resultTypesBitSet, resultObjects.copyToArray(new AnalysisObject[resultObjects.size()]));
        assert !result.equals(s1) : "speculation code should prevent this case";
        /* The result can be equal to s2 only if s1 and s2 have the same number of types. */
        if (s1.typesCount() == s2.typesCount() && result.equals(s2)) {
            return s2.forCanBeNull(bb, resultCanBeNull);
        }
        PointsToStats.registerUnionOperation(bb, s1, s2, result);
        return result;
    }
}
Also used : AnalysisObject(com.oracle.graal.pointsto.flow.context.object.AnalysisObject) BitSet(java.util.BitSet)

Example 12 with AnalysisObject

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

the class TypeStateUtils method checkUnionSize.

private static AnalysisObject[] checkUnionSize(BigBang bb, AnalysisObject[] oa1, AnalysisObject[] oa2, AnalysisObject[] result) {
    assert result.length >= 2;
    if (PointstoOptions.LimitObjectArrayLength.getValue(bb.getOptions()) && (result.length > PointstoOptions.MaxObjectSetSize.getValue(bb.getOptions()))) {
        AnalysisObject rObj = result[0].type().getContextInsensitiveAnalysisObject();
        bb.analysisPolicy().noteMerge(bb, oa1);
        bb.analysisPolicy().noteMerge(bb, oa2);
        bb.analysisPolicy().noteMerge(bb, rObj);
        return new AnalysisObject[] { rObj };
    } else {
        return result;
    }
}
Also used : AnalysisObject(com.oracle.graal.pointsto.flow.context.object.AnalysisObject)

Example 13 with AnalysisObject

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

the class MultiTypeState method checkObjects.

private boolean checkObjects(OptionValues options) {
    assert PointstoOptions.ExtendedAsserts.getValue(options);
    for (int idx = 0; idx < objects.length - 1; idx++) {
        AnalysisObject o0 = objects[idx];
        AnalysisObject o1 = objects[idx + 1];
        assert o0 != null && o1 != null : "Object state must contain non null elements.";
        /* Check that the objects array are sorted by type. */
        assert (o0.type().equals(o1.type()) && o0.getId() < o1.getId()) || o0.type().getId() < o1.type().getId() : "Analysis objects must be sorted by type ID and ID.";
        /* Check that the bit is set for the types. */
        assert typesBitSet.get(o0.type().getId());
        assert typesBitSet.get(o1.type().getId());
    }
    return true;
}
Also used : AnalysisObject(com.oracle.graal.pointsto.flow.context.object.AnalysisObject)

Example 14 with AnalysisObject

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

the class SingleTypeState method checkObjects.

protected boolean checkObjects(OptionValues options) {
    assert PointstoOptions.ExtendedAsserts.getValue(options);
    /* Check that the objects array are sorted by type. */
    for (int idx = 0; idx < objects.length - 1; idx++) {
        AnalysisObject o0 = objects[idx];
        AnalysisObject o1 = objects[idx + 1];
        assert o0 != null && o1 != null : "Object state must contain non null elements.";
        assert o0.type().equals(o1.type()) : "Single type state objects must have the same type.";
        /*
             * Check that the objects are sorted by ID. Since the objects should be unique (context
             * sensitive objects are merged when they have the same type during the union
             * operation), we use < for the test.
             */
        assert o0.getId() < o1.getId() : "Analysis objects must be sorted by ID.";
    }
    return true;
}
Also used : AnalysisObject(com.oracle.graal.pointsto.flow.context.object.AnalysisObject)

Example 15 with AnalysisObject

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

the class UnknownTypeState method doUnion.

private static TypeState doUnion(BigBang bb, MultiTypeState s1, SingleTypeState s2) {
    boolean resultCanBeNull = s1.canBeNull() || s2.canBeNull();
    if (s2.objects.length == 1 && s1.containsObject(s2.objects[0])) {
        /*
             * Speculate that s2 has a single object and s1 already contains that object. This
             * happens often during object scanning where we repeatedly add the scanned constants to
             * field or array elements flows. The binary search executed by containsObject should be
             * faster than the linear search bellow.
             */
        return s1.forCanBeNull(bb, resultCanBeNull);
    }
    if (s1.containsType(s2.exactType())) {
        /* Objects of the same type as s2 are contained in s1. */
        /* Get the range of objects in s1 corresponding to the type of s2. */
        Range typeRange = s1.findTypeRange(s2.exactType());
        /* Get the slice of objects in s1 corresponding to the type of s2. */
        AnalysisObject[] s1ObjectsSlice = s1.objectsArray(typeRange);
        /* Create the resulting objects array. */
        AnalysisObject[] unionObjects = TypeStateUtils.union(bb, s1ObjectsSlice, s2.objects);
        /* Check if s1 contains s2's objects for this type. */
        if (unionObjects == s1ObjectsSlice) {
            return s1.forCanBeNull(bb, resultCanBeNull);
        }
        /*
             * Due to the test above and to the fact that TypeStateUtils.union checks if one array
             * contains the other the union set cannot be equal to s1's objects slice.
             */
        assert !PointstoOptions.ExtendedAsserts.getValue(bb.getOptions()) || !Arrays.equals(unionObjects, s1ObjectsSlice);
        /*
             * Replace the s1 objects slice of the same type as s2 with the union objects and create
             * a new state.
             */
        int resultSize = s1.objects.length + unionObjects.length - s1ObjectsSlice.length;
        AnalysisObject[] resultObjects = new AnalysisObject[resultSize];
        System.arraycopy(s1.objects, 0, resultObjects, 0, typeRange.left);
        System.arraycopy(unionObjects, 0, resultObjects, typeRange.left, unionObjects.length);
        System.arraycopy(s1.objects, typeRange.right, resultObjects, typeRange.left + unionObjects.length, s1.objects.length - typeRange.right);
        /* The types bit set of the result and s1 are the same. */
        int properties = bb.analysisPolicy().makePopertiesForUnion(s1, s2);
        MultiTypeState result = new MultiTypeState(bb, resultCanBeNull, properties, s1.typesBitSet, resultObjects);
        assert !result.equals(s1);
        /*
             * No need to check the result size against the all-instantiated since the type count
             * didn't change.
             */
        PointsToStats.registerUnionOperation(bb, s1, s2, result);
        return result;
    } else {
        AnalysisObject[] resultObjects;
        if (s2.exactType().getId() < s1.firstType().getId()) {
            resultObjects = TypeStateUtils.concat(s2.objects, s1.objects);
        } else if (s2.exactType().getId() > s1.lastType().getId()) {
            resultObjects = TypeStateUtils.concat(s1.objects, s2.objects);
        } else {
            /* Find insertion point within the s1.objects. */
            int idx1 = 0;
            while (idx1 < s1.objects.length && s1.objects[idx1].type().getId() < s2.exactType().getId()) {
                idx1++;
            }
            /* Create the resulting objects array and insert the s2 objects. */
            resultObjects = new AnalysisObject[s1.objects.length + s2.objects.length];
            System.arraycopy(s1.objects, 0, resultObjects, 0, idx1);
            System.arraycopy(s2.objects, 0, resultObjects, idx1, s2.objects.length);
            System.arraycopy(s1.objects, idx1, resultObjects, idx1 + s2.objects.length, s1.objects.length - idx1);
        }
        /* Create the types bit set by adding the s2 type to avoid walking the objects. */
        BitSet typesBitSet = TypeStateUtils.set(s1.typesBitSet, s2.exactType().getId());
        int properties = bb.analysisPolicy().makePopertiesForUnion(s1, s2);
        MultiTypeState result = new MultiTypeState(bb, resultCanBeNull, properties, typesBitSet, resultObjects);
        PointsToStats.registerUnionOperation(bb, s1, s2, result);
        return result;
    }
}
Also used : AnalysisObject(com.oracle.graal.pointsto.flow.context.object.AnalysisObject) BitSet(java.util.BitSet) Range(com.oracle.graal.pointsto.typestate.MultiTypeState.Range)

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