use of com.oracle.graal.pointsto.typestate.TypeState 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.typestate.TypeState in project graal by oracle.
the class ProxyTypeFlow method update.
@Override
public void update(BigBang bb) {
// propagate input state to uses
TypeState curState = input.getState();
for (TypeFlow<?> use : getUses()) {
use.addState(bb, curState);
}
notifyObservers(bb);
}
use of com.oracle.graal.pointsto.typestate.TypeState in project graal by oracle.
the class TypeFlow method addState.
public boolean addState(BigBang bb, TypeState add, boolean postFlow) {
PointsToStats.registerTypeFlowUpdate(bb, this, add);
TypeState before;
TypeState after;
TypeState filteredAdd;
do {
before = state;
filteredAdd = filter(bb, add);
after = TypeState.forUnion(bb, before, filteredAdd);
if (after.equals(before)) {
return false;
}
} while (!STATE_UPDATER.compareAndSet(this, before, after));
PointsToStats.registerTypeFlowSuccessfulUpdate(bb, this, add);
/*
* Checkcast and instanceof type flows no longer reflect a type state that contains only the
* types assignable to the declared type; they keep track of all the types discovered during
* analysis and are always followed by a filter type flow that implements the filter
* operation based on the declared type.
*/
assert !PointstoOptions.ExtendedAsserts.getValue(bb.getOptions()) || this instanceof InstanceOfTypeFlow || after.verifyDeclaredType(declaredType) : "declaredType: " + declaredType.toJavaName(true) + " after: " + after + " before: " + before + " this: " + this;
if (postFlow) {
bb.postFlow(this);
}
return true;
}
use of com.oracle.graal.pointsto.typestate.TypeState in project graal by oracle.
the class FilterTypeFlow method filter.
@Override
public TypeState filter(BigBang bb, TypeState update) {
if (update.isUnknown()) {
// Filtering UnknownTypeState would otherwise return EmptyTypeState.
AnalysisMethod method = (AnalysisMethod) source.graph().method();
bb.reportIllegalUnknownUse(method, source, "Illegal: Filter of UnknownTypeState objects.");
return TypeState.forEmpty();
}
TypeState result;
if (isExact) {
/*
* If the filter is exact we only check the update state against the exact type, and not
* its entire hierarchy.
*/
if (isAssignable) {
result = TypeState.forIntersection(bb, update, TypeState.forExactType(bb, type, includeNull));
} else {
result = TypeState.forSubtraction(bb, update, TypeState.forExactType(bb, type, !includeNull));
}
} else {
/*
* If the filter is not exact we check the update state against the entire hierarchy,
* not only the exact type (AnalysisType.getTypeFlow() returns the type plus all its
* instantiated sub-types).
*/
if (isAssignable) {
result = TypeState.forIntersection(bb, update, type.getTypeFlow(bb, includeNull).getState());
} else {
result = TypeState.forSubtraction(bb, update, type.getTypeFlow(bb, !includeNull).getState());
}
}
return result;
}
use of com.oracle.graal.pointsto.typestate.TypeState in project graal by oracle.
the class NativeImageGenerator method checkUniverse.
private void checkUniverse() {
/*
* Check that the type states for method parameters and fields are compatible with the
* declared type. This is required for interface types because interfaces are not trusted
* according to the Java language specification, but we trust all interface types (see
* HostedType.isTrustedInterfaceType)
*
* TODO Enable checks for non-interface types too.
*/
for (AnalysisMethod method : aUniverse.getMethods()) {
for (int i = 0; i < method.getTypeFlow().getOriginalMethodFlows().getParameters().length; i++) {
TypeState state = method.getTypeFlow().getParameterTypeState(bigbang, i);
if (state != null) {
AnalysisType declaredType = method.getTypeFlow().getOriginalMethodFlows().getParameter(i).getDeclaredType();
if (declaredType.isInterface()) {
state = TypeState.forSubtraction(bigbang, state, declaredType.getTypeFlow(bigbang, true).getState());
if (!state.isEmpty()) {
bigbang.getUnsupportedFeatures().addMessage(method.format("%H.%n(%p)"), method, "Method parameter " + i + " has declaredType " + declaredType.toJavaName(true) + " and incompatible types in state: " + state);
}
}
}
}
}
for (AnalysisField field : aUniverse.getFields()) {
TypeState state = field.getTypeState();
if (state != null) {
AnalysisType declaredType = field.getType();
if (declaredType.isInterface()) {
state = TypeState.forSubtraction(bigbang, state, declaredType.getTypeFlow(bigbang, true).getState());
if (!state.isEmpty()) {
bigbang.getUnsupportedFeatures().addMessage(field.format("%H.%n"), null, "Field has declaredType " + declaredType.toJavaName(true) + " and incompatible types in state: " + state);
}
}
}
}
if (SubstrateOptions.VerifyNamingConventions.getValue()) {
for (AnalysisMethod method : aUniverse.getMethods()) {
if ((method.isInvoked() || method.isImplementationInvoked()) && method.getAnnotation(Fold.class) == null) {
checkName(method.format("%H.%n(%p)"), method);
}
}
for (AnalysisField field : aUniverse.getFields()) {
if (field.isAccessed()) {
checkName(field.format("%H.%n"), null);
}
}
for (AnalysisType type : aUniverse.getTypes()) {
if ((type.isInstantiated() || type.isInTypeCheck())) {
checkName(type.toJavaName(true), null);
}
}
}
/*
* Entry points use a different calling convention (the native C ABI calling convention), so
* they must not be called from other Java methods.
*/
for (AnalysisMethod method : aUniverse.getMethods()) {
if (method.isEntryPoint()) {
List<AnalysisMethod> invocations = method.getJavaInvocations();
if (invocations.size() > 0) {
String name = method.format("%H.%n(%p)");
StringBuilder msg = new StringBuilder("Native entry point is also called from within Java. Invocations: ");
String sep = "";
for (AnalysisMethod invocation : invocations) {
msg.append(sep).append(invocation.format("%H.%n(%p)"));
sep = ", ";
}
bigbang.getUnsupportedFeatures().addMessage(name, method, msg.toString());
}
}
}
// the unsupported features are reported after checkUniverse is invoked
}
Aggregations