Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,13 @@ public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, Jav
AnalysisType fieldType = bb.getMetaAccess().lookupJavaType(bb.getSnippetReflectionProvider().asObject(Object.class, fieldValue).getClass());
assert fieldType.isInstantiated() : fieldType;

/*
* *ALL* constants are scanned after each analysis iteration, thus the fieldType will
* eventually be added to the AllInstantiatedTypeFlow and the field type flow will
* eventually be updated.
*/

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().containsObject(constantObject)) {
/* Add the new constant to the field's flow state. */
TypeState constantTypeState = TypeState.forNonNullObject(bb, constantObject);
fieldTypeFlow.addState(bb, constantTypeState);
}
/* 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().containsObject(constantObject)) {
/* Add the new constant to the field's flow state. */
TypeState constantTypeState = TypeState.forNonNullObject(bb, constantObject);
fieldTypeFlow.addState(bb, constantTypeState);
}
}

Expand Down Expand Up @@ -107,19 +99,13 @@ public void forNullArrayElement(JavaConstant array, AnalysisType arrayType, int

@Override
public void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int elementIndex) {
/*
* *ALL* constants are scanned after each analysis iteration, thus the elementType will
* eventually be added to the AllInstantiatedTypeFlow and the array elements flow will
* eventually be updated.
*/
if (bb.getAllInstantiatedTypeFlow().getState().containsType(elementType)) {
ArrayElementsTypeFlow arrayObjElementsFlow = getArrayElementsFlow(array, arrayType);
AnalysisObject constantObject = bb.analysisPolicy().createConstantObject(bb, elementConstant, elementType);
if (!arrayObjElementsFlow.getState().containsObject(constantObject)) {
/* Add the constant element to the constant's array type flow. */
TypeState elementTypeState = TypeState.forNonNullObject(bb, constantObject);
arrayObjElementsFlow.addState(bb, elementTypeState);
}
assert elementType.isInstantiated() : elementType;
ArrayElementsTypeFlow arrayObjElementsFlow = getArrayElementsFlow(array, arrayType);
AnalysisObject constantObject = bb.analysisPolicy().createConstantObject(bb, elementConstant, elementType);
if (!arrayObjElementsFlow.getState().containsObject(constantObject)) {
/* Add the constant element to the constant's array type flow. */
TypeState elementTypeState = TypeState.forNonNullObject(bb, constantObject);
arrayObjElementsFlow.addState(bb, elementTypeState);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public abstract class BigBang {

protected final boolean trackTypeFlowInputs;
protected final boolean reportAnalysisStatistics;
protected final boolean extendedAsserts;

/**
* Processing queue.
Expand Down Expand Up @@ -160,6 +161,7 @@ public BigBang(OptionValues options, AnalysisUniverse universe, HostedProviders
if (reportAnalysisStatistics) {
PointsToStats.init(this);
}
extendedAsserts = PointstoOptions.ExtendedAsserts.getValue(options);

unsafeLoads = new ConcurrentHashMap<>();
unsafeStores = new ConcurrentHashMap<>();
Expand Down Expand Up @@ -194,6 +196,10 @@ public boolean reportAnalysisStatistics() {
return reportAnalysisStatistics;
}

public boolean extendedAsserts() {
return extendedAsserts;
}

public OptionValues getOptions() {
return options;
}
Expand Down Expand Up @@ -358,6 +364,10 @@ public TypeFlow<?> getAllInstantiatedTypeFlow() {
return objectType.getTypeFlow(this, true);
}

public TypeState getAllInstantiatedTypes() {
return getAllInstantiatedTypeFlow().getState();
}

public TypeFlow<?> getAllSynchronizedTypeFlow() {
return allSynchronizedTypeFlow;
}
Expand All @@ -369,7 +379,7 @@ public TypeState getAllSynchronizedTypeState() {
* monitors.
*/
if (allSynchronizedTypeFlow.isSaturated()) {
return getAllInstantiatedTypeFlow().getState();
return getAllInstantiatedTypes();
}
return allSynchronizedTypeFlow.getState();
}
Expand Down Expand Up @@ -627,7 +637,6 @@ private void checkObjectGraph() throws InterruptedException {
} else {
objectScanner.scanBootImageHeapRoots(null, null);
}
AnalysisType.updateAssignableTypes(this);
}

public HeapScanningPolicy scanningPolicy() {
Expand Down Expand Up @@ -821,7 +830,7 @@ public void printHeader() {

@Override
public void print() {
System.out.format("%5d %5d %5d |", numParsedGraphs.get(), getAllInstantiatedTypeFlow().getState().typesCount(), universe.getNextTypeId());
System.out.format("%5d %5d %5d |", numParsedGraphs.get(), getAllInstantiatedTypes().typesCount(), universe.getNextTypeId());
super.print();
System.out.println();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ public void onObservedSaturated(BigBang bb, TypeFlow<?> observed) {

/*
* The receiver object flow of the invoke operation is saturated; it will stop sending
* notificatons. Swap the invoke flow with the unique, context-insensitive invoke flow
* notifications. Swap the invoke flow with the unique, context-insensitive invoke flow
* corresponding to the target method, which is already registered as an observer for
* the type flow of the receiver type and therefore saturated. This is a conservative
* approximation and this invoke will reach all possible callees.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ public final void scanConstant(JavaConstant value, ScanReason reason, WorklistEn
return;
}
if (!bb.scanningPolicy().scanConstant(bb, value)) {
analysisType(bb, valueObj).registerAsInHeap();
return;
}
if (scannedObjects.putAndAcquire(valueObj) == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public final boolean addState(BigBang bb, TypeState add) {
*/
protected TypeState filterObjectState(BigBang bb, TypeState objectState) {
if (bb.analysisPolicy().relaxTypeFlowConstraints()) {
return TypeState.forIntersection(bb, objectState, field.getDeclaringClass().getTypeFlow(bb, true).getState());
return TypeState.forIntersection(bb, objectState, field.getDeclaringClass().getAssignableTypes(true));
}
return objectState;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@

public final class AllInstantiatedTypeFlow extends TypeFlow<AnalysisType> {

public AllInstantiatedTypeFlow(AnalysisType declaredType) {
super(declaredType, declaredType);
public AllInstantiatedTypeFlow(AnalysisType declaredType, boolean canBeNull) {
super(declaredType, declaredType, canBeNull);
}

public AllInstantiatedTypeFlow(AnalysisType declaredType, TypeState state) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public boolean canSaturate() {
@Override
protected void onInputSaturated(BigBang bb, TypeFlow<?> input) {
/*
* When an array store is saturated conservativelly assume that the array can contain any
* When an array store is saturated conservatively assume that the array can contain any
* subtype of its declared type.
*/
getDeclaredType().getTypeFlow(bb, true).addUse(bb, this);
Expand All @@ -79,7 +79,7 @@ public TypeState filter(BigBang bb, TypeState update) {
* conversion. At runtime that will throw an ArrayStoreException but during the analysis
* we can detect such cases and filter out the incompatible types.
*/
return TypeState.forIntersection(bb, update, declaredType.getTypeFlow(bb, true).getState());
return TypeState.forIntersection(bb, update, declaredType.getAssignableTypes(true));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public TypeState filter(BigBang bb, TypeState update) {
return update;
} else {
/* Filter the incoming state with the field type. */
return TypeState.forIntersection(bb, update, declaredType.getTypeFlow(bb, true).getState());
return TypeState.forIntersection(bb, update, declaredType.getAssignableTypes(true));
}
}

Expand All @@ -62,6 +62,16 @@ protected void onInputSaturated(BigBang bb, TypeFlow<?> input) {
swapOut(bb, declaredType.getTypeFlow(bb, true));
}

@Override
protected void notifyUseOfSaturation(BigBang bb, TypeFlow<?> use) {
swapAtUse(bb, declaredType.getTypeFlow(bb, true), use);
}

@Override
protected void notifyObserverOfSaturation(BigBang bb, TypeFlow<?> observer) {
swapAtObserver(bb, declaredType.getTypeFlow(bb, true), observer);
}

@Override
public String toString() {
return "FieldFilterTypeFlow<" + source + ">";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,13 @@ public boolean canSaturate() {
@Override
protected void onInputSaturated(BigBang bb, TypeFlow<?> input) {
/*
* When a field store is saturated conservativelly assume that the field state can contain
* When a field store is saturated conservatively assume that the field state can contain
* any subtype of its declared type.
*/
getDeclaredType().getTypeFlow(bb, true).addUse(bb, this);
}

/** The filter flow is used for unsafe writes and initialiazed on demand. */
/** The filter flow is used for unsafe writes and initialized on demand. */
public FieldFilterTypeFlow filterFlow(BigBang bb) {
assert source.isUnsafeAccessed() : "Filter flow requested for non unsafe accessed field.";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ public TypeState filter(BigBang bb, TypeState update) {
* instantiated sub-types).
*/
if (isAssignable) {
result = TypeState.forIntersection(bb, update, declaredType.getTypeFlow(bb, includeNull).getState());
result = TypeState.forIntersection(bb, update, declaredType.getAssignableTypes(includeNull));
} else {
result = TypeState.forSubtraction(bb, update, declaredType.getTypeFlow(bb, !includeNull).getState());
result = TypeState.forSubtraction(bb, update, declaredType.getAssignableTypes(!includeNull));
}
}
return result;
Expand All @@ -102,28 +102,32 @@ public TypeState filter(BigBang bb, TypeState update) {
@Override
protected void onInputSaturated(BigBang bb, TypeFlow<?> input) {
if (isAssignable) {
TypeFlow<?> sourceFlow = declaredType.getTypeFlow(bb, includeNull);

/*
* First mark this flow as saturated, then swap it out at its uses/observers with its
* declared type flow. Marking this flow as saturated first is important: if there are
* any uses or observers *in-flight*, i.e., not yet registered at this point, trying to
* swap-out will have no effect on those. However, if this flow is already marked as
* saturated when the use or observer *lands*, even if that happens while/after
* swapping-out, then the corresponding use or observer will be notified of its input
* saturation. Otherwise it may neighter get the saturation signal OR get swapped-out.
*
* The downside in the later case is that the input/observer will lose the more precise
* type information that swapping-out would have provided and will just use the more
* conservative approximation, e.g., the target method declared type for invokes.
*/
/* Swap this flow out at its uses/observers with its declared type flow. */
setSaturated();
swapOut(bb, sourceFlow);
swapOut(bb, declaredType.getTypeFlow(bb, includeNull));
} else {
super.onInputSaturated(bb, input);
}
}

@Override
protected void notifyUseOfSaturation(BigBang bb, TypeFlow<?> use) {
if (isAssignable) {
swapAtUse(bb, declaredType.getTypeFlow(bb, includeNull), use);
} else {
super.notifyUseOfSaturation(bb, use);
}
}

@Override
protected void notifyObserverOfSaturation(BigBang bb, TypeFlow<?> observer) {
if (isAssignable) {
swapAtObserver(bb, declaredType.getTypeFlow(bb, includeNull), observer);
} else {
super.notifyObserverOfSaturation(bb, observer);
}
}

@Override
public boolean addState(BigBang bb, TypeState add) {
assert this.isClone();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public int position() {
@Override
public String toString() {
StringBuilder str = new StringBuilder();
str.append("FormalParamFlow").append("[").append(method.format("%H.%n")).append("]").append("[").append(position).append("]<").append(getState()).append(">");
str.append("FormalParamFlow").append("[").append(method.format("%H.%n(%p)")).append("]").append("[").append(position).append("]<").append(getState()).append(">");
return str.toString();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,20 @@ public TypeState filter(BigBang bb, TypeState newState) {
return declaredTypeFilter(bb, newState).forNonNull(bb);
}

/**
* The formal receiver type flow, i.e., the type flow of the 'this' parameter, is linked with
* the actual receiver type flow through a non-state-transfer link, i.e., a link that exists
* only for a proper iteration of type flow graphs. This happens because the formal receiver ,
* i.e., 'this' parameter, state must ONLY reflect those objects of the actual receiver that
* generated the context for the method clone which it belongs to. A direct link would instead
* transfer all the objects of compatible type from the actual receiver to the formal receiver.
* The formal receiver state for the non-initial parameters is updated through the
* FormalReceiverTypeFlow.addReceiverState method invoked directly from
* VirtualInvokeTypeFlow.update, SpecialInvokeTypeFlow.update or from
* InitialReceiverTypeFlow.update.
*/
@Override
public boolean addState(BigBang bb, TypeState add) {
/*
* The formal receiver type flow, i.e., the type flow of the 'this' parameter is linked with
* the actual receiver type flow through a non-state-transfer link, i.e., a link that exists
* only for a proper iteration of type flow graphs. This happens because the formal receiver
* , i.e., 'this' parameter, state must ONLY reflect those objects of the actual receiver
* that generated the context for the method clone which it belongs to. A direct link would
* instead transfer all the objects of compatible type from the actual receiver to the
* formal receiver. The formal receiver state for the non-initial parameters is updated
* through the FormalReceiverTypeFlow.addReceiverState method invoked directly from
* VirtualInvokeTypeFlow.update, SpecialInvokeTypeFlow.update or from
* InitialReceiverTypeFlow.update.
*/
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,20 @@ public TypeState filter(BigBang bb, TypeState newState) {
return newState.forNonNull(bb);
}

/**
* The state of the formal receiver type flow cannot be updated directly, thus
* {@link FormalReceiverTypeFlow#addReceiverState(BigBang, TypeState)} needs to be used. See
* {@link FormalReceiverTypeFlow#addState(BigBang, TypeState)} for a complete explanation.
*/
@Override
public boolean addUse(BigBang bb, TypeFlow<?> use) {
boolean useAdded = super.addUse(bb, use);
if (useAdded) {
((FormalReceiverTypeFlow) use).addReceiverState(bb, getState());
}
return useAdded;
}

@Override
public void update(BigBang bb) {
TypeState curState = getState();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public boolean addState(BigBang bb, TypeState add) {
*/
protected TypeState filterReceiverState(BigBang bb, TypeState invokeState) {
if (bb.analysisPolicy().relaxTypeFlowConstraints()) {
return TypeState.forIntersection(bb, invokeState, receiverType.getTypeFlow(bb, true).getState());
return TypeState.forIntersection(bb, invokeState, receiverType.getAssignableTypes(true));
}
return invokeState;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ public TypeState filter(BigBang bb, TypeState update) {
return update;
} else {
/* Filter the incoming state with the partition type. */
return TypeState.forIntersection(bb, update, partitionType.getTypeFlow(bb, true).getState());
return TypeState.forIntersection(bb, update, partitionType.getAssignableTypes(true));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ public TypeState filter(BigBang bb, TypeState update) {
return update;
} else {
/* Filter the incoming state with the partition type. */
return TypeState.forIntersection(bb, update, partitionType.getTypeFlow(bb, true).getState());
return TypeState.forIntersection(bb, update, partitionType.getAssignableTypes(true));
}
}

Expand Down
Loading