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