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;
}
}
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;
}
}
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;
}
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;
}
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;
}
}
Aggregations