Skip to content

Commit e34d551

Browse files
committed
[GR-32057] Propagate assignable types eagerly.
PullRequest: graal/9471
2 parents 2a7411e + 58bb7b7 commit e34d551

25 files changed

+358
-373
lines changed

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AnalysisObjectScanner.java

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -61,21 +61,13 @@ public void forNonNullFieldValue(JavaConstant receiver, AnalysisField field, Jav
6161
AnalysisType fieldType = bb.getMetaAccess().lookupJavaType(bb.getSnippetReflectionProvider().asObject(Object.class, fieldValue).getClass());
6262
assert fieldType.isInstantiated() : fieldType;
6363

64-
/*
65-
* *ALL* constants are scanned after each analysis iteration, thus the fieldType will
66-
* eventually be added to the AllInstantiatedTypeFlow and the field type flow will
67-
* eventually be updated.
68-
*/
69-
70-
if (bb.getAllInstantiatedTypeFlow().getState().containsType(fieldType)) {
71-
/* Add the constant value object to the field's type flow. */
72-
FieldTypeFlow fieldTypeFlow = getFieldTypeFlow(field, receiver);
73-
AnalysisObject constantObject = bb.analysisPolicy().createConstantObject(bb, fieldValue, fieldType);
74-
if (!fieldTypeFlow.getState().containsObject(constantObject)) {
75-
/* Add the new constant to the field's flow state. */
76-
TypeState constantTypeState = TypeState.forNonNullObject(bb, constantObject);
77-
fieldTypeFlow.addState(bb, constantTypeState);
78-
}
64+
/* Add the constant value object to the field's type flow. */
65+
FieldTypeFlow fieldTypeFlow = getFieldTypeFlow(field, receiver);
66+
AnalysisObject constantObject = bb.analysisPolicy().createConstantObject(bb, fieldValue, fieldType);
67+
if (!fieldTypeFlow.getState().containsObject(constantObject)) {
68+
/* Add the new constant to the field's flow state. */
69+
TypeState constantTypeState = TypeState.forNonNullObject(bb, constantObject);
70+
fieldTypeFlow.addState(bb, constantTypeState);
7971
}
8072
}
8173

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

108100
@Override
109101
public void forNonNullArrayElement(JavaConstant array, AnalysisType arrayType, JavaConstant elementConstant, AnalysisType elementType, int elementIndex) {
110-
/*
111-
* *ALL* constants are scanned after each analysis iteration, thus the elementType will
112-
* eventually be added to the AllInstantiatedTypeFlow and the array elements flow will
113-
* eventually be updated.
114-
*/
115-
if (bb.getAllInstantiatedTypeFlow().getState().containsType(elementType)) {
116-
ArrayElementsTypeFlow arrayObjElementsFlow = getArrayElementsFlow(array, arrayType);
117-
AnalysisObject constantObject = bb.analysisPolicy().createConstantObject(bb, elementConstant, elementType);
118-
if (!arrayObjElementsFlow.getState().containsObject(constantObject)) {
119-
/* Add the constant element to the constant's array type flow. */
120-
TypeState elementTypeState = TypeState.forNonNullObject(bb, constantObject);
121-
arrayObjElementsFlow.addState(bb, elementTypeState);
122-
}
102+
assert elementType.isInstantiated() : elementType;
103+
ArrayElementsTypeFlow arrayObjElementsFlow = getArrayElementsFlow(array, arrayType);
104+
AnalysisObject constantObject = bb.analysisPolicy().createConstantObject(bb, elementConstant, elementType);
105+
if (!arrayObjElementsFlow.getState().containsObject(constantObject)) {
106+
/* Add the constant element to the constant's array type flow. */
107+
TypeState elementTypeState = TypeState.forNonNullObject(bb, constantObject);
108+
arrayObjElementsFlow.addState(bb, elementTypeState);
123109
}
124110
}
125111

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public abstract class BigBang {
108108

109109
protected final boolean trackTypeFlowInputs;
110110
protected final boolean reportAnalysisStatistics;
111+
protected final boolean extendedAsserts;
111112

112113
/**
113114
* Processing queue.
@@ -160,6 +161,7 @@ public BigBang(OptionValues options, AnalysisUniverse universe, HostedProviders
160161
if (reportAnalysisStatistics) {
161162
PointsToStats.init(this);
162163
}
164+
extendedAsserts = PointstoOptions.ExtendedAsserts.getValue(options);
163165

164166
unsafeLoads = new ConcurrentHashMap<>();
165167
unsafeStores = new ConcurrentHashMap<>();
@@ -194,6 +196,10 @@ public boolean reportAnalysisStatistics() {
194196
return reportAnalysisStatistics;
195197
}
196198

199+
public boolean extendedAsserts() {
200+
return extendedAsserts;
201+
}
202+
197203
public OptionValues getOptions() {
198204
return options;
199205
}
@@ -358,6 +364,10 @@ public TypeFlow<?> getAllInstantiatedTypeFlow() {
358364
return objectType.getTypeFlow(this, true);
359365
}
360366

367+
public TypeState getAllInstantiatedTypes() {
368+
return getAllInstantiatedTypeFlow().getState();
369+
}
370+
361371
public TypeFlow<?> getAllSynchronizedTypeFlow() {
362372
return allSynchronizedTypeFlow;
363373
}
@@ -369,7 +379,7 @@ public TypeState getAllSynchronizedTypeState() {
369379
* monitors.
370380
*/
371381
if (allSynchronizedTypeFlow.isSaturated()) {
372-
return getAllInstantiatedTypeFlow().getState();
382+
return getAllInstantiatedTypes();
373383
}
374384
return allSynchronizedTypeFlow.getState();
375385
}
@@ -627,7 +637,6 @@ private void checkObjectGraph() throws InterruptedException {
627637
} else {
628638
objectScanner.scanBootImageHeapRoots(null, null);
629639
}
630-
AnalysisType.updateAssignableTypes(this);
631640
}
632641

633642
public HeapScanningPolicy scanningPolicy() {
@@ -821,7 +830,7 @@ public void printHeader() {
821830

822831
@Override
823832
public void print() {
824-
System.out.format("%5d %5d %5d |", numParsedGraphs.get(), getAllInstantiatedTypeFlow().getState().typesCount(), universe.getNextTypeId());
833+
System.out.format("%5d %5d %5d |", numParsedGraphs.get(), getAllInstantiatedTypes().typesCount(), universe.getNextTypeId());
825834
super.print();
826835
System.out.println();
827836
}

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/DefaultAnalysisPolicy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ public void onObservedSaturated(BigBang bb, TypeFlow<?> observed) {
248248

249249
/*
250250
* The receiver object flow of the invoke operation is saturated; it will stop sending
251-
* notificatons. Swap the invoke flow with the unique, context-insensitive invoke flow
251+
* notifications. Swap the invoke flow with the unique, context-insensitive invoke flow
252252
* corresponding to the target method, which is already registered as an observer for
253253
* the type flow of the receiver type and therefore saturated. This is a conservative
254254
* approximation and this invoke will reach all possible callees.

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ public final void scanConstant(JavaConstant value, ScanReason reason, WorklistEn
246246
return;
247247
}
248248
if (!bb.scanningPolicy().scanConstant(bb, value)) {
249+
analysisType(bb, valueObj).registerAsInHeap();
249250
return;
250251
}
251252
if (scannedObjects.putAndAcquire(valueObj) == null) {

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AccessFieldTypeFlow.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public final boolean addState(BigBang bb, TypeState add) {
6666
*/
6767
protected TypeState filterObjectState(BigBang bb, TypeState objectState) {
6868
if (bb.analysisPolicy().relaxTypeFlowConstraints()) {
69-
return TypeState.forIntersection(bb, objectState, field.getDeclaringClass().getTypeFlow(bb, true).getState());
69+
return TypeState.forIntersection(bb, objectState, field.getDeclaringClass().getAssignableTypes(true));
7070
}
7171
return objectState;
7272
}

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AllInstantiatedTypeFlow.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030

3131
public final class AllInstantiatedTypeFlow extends TypeFlow<AnalysisType> {
3232

33-
public AllInstantiatedTypeFlow(AnalysisType declaredType) {
34-
super(declaredType, declaredType);
33+
public AllInstantiatedTypeFlow(AnalysisType declaredType, boolean canBeNull) {
34+
super(declaredType, declaredType, canBeNull);
3535
}
3636

3737
public AllInstantiatedTypeFlow(AnalysisType declaredType, TypeState state) {

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/ArrayElementsTypeFlow.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public boolean canSaturate() {
6161
@Override
6262
protected void onInputSaturated(BigBang bb, TypeFlow<?> input) {
6363
/*
64-
* When an array store is saturated conservativelly assume that the array can contain any
64+
* When an array store is saturated conservatively assume that the array can contain any
6565
* subtype of its declared type.
6666
*/
6767
getDeclaredType().getTypeFlow(bb, true).addUse(bb, this);
@@ -79,7 +79,7 @@ public TypeState filter(BigBang bb, TypeState update) {
7979
* conversion. At runtime that will throw an ArrayStoreException but during the analysis
8080
* we can detect such cases and filter out the incompatible types.
8181
*/
82-
return TypeState.forIntersection(bb, update, declaredType.getTypeFlow(bb, true).getState());
82+
return TypeState.forIntersection(bb, update, declaredType.getAssignableTypes(true));
8383
}
8484
}
8585

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/FieldFilterTypeFlow.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public TypeState filter(BigBang bb, TypeState update) {
5151
return update;
5252
} else {
5353
/* Filter the incoming state with the field type. */
54-
return TypeState.forIntersection(bb, update, declaredType.getTypeFlow(bb, true).getState());
54+
return TypeState.forIntersection(bb, update, declaredType.getAssignableTypes(true));
5555
}
5656
}
5757

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

65+
@Override
66+
protected void notifyUseOfSaturation(BigBang bb, TypeFlow<?> use) {
67+
swapAtUse(bb, declaredType.getTypeFlow(bb, true), use);
68+
}
69+
70+
@Override
71+
protected void notifyObserverOfSaturation(BigBang bb, TypeFlow<?> observer) {
72+
swapAtObserver(bb, declaredType.getTypeFlow(bb, true), observer);
73+
}
74+
6575
@Override
6676
public String toString() {
6777
return "FieldFilterTypeFlow<" + source + ">";

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/FieldTypeFlow.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,13 @@ public boolean canSaturate() {
8787
@Override
8888
protected void onInputSaturated(BigBang bb, TypeFlow<?> input) {
8989
/*
90-
* When a field store is saturated conservativelly assume that the field state can contain
90+
* When a field store is saturated conservatively assume that the field state can contain
9191
* any subtype of its declared type.
9292
*/
9393
getDeclaredType().getTypeFlow(bb, true).addUse(bb, this);
9494
}
9595

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

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/FilterTypeFlow.java

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ public TypeState filter(BigBang bb, TypeState update) {
9191
* instantiated sub-types).
9292
*/
9393
if (isAssignable) {
94-
result = TypeState.forIntersection(bb, update, declaredType.getTypeFlow(bb, includeNull).getState());
94+
result = TypeState.forIntersection(bb, update, declaredType.getAssignableTypes(includeNull));
9595
} else {
96-
result = TypeState.forSubtraction(bb, update, declaredType.getTypeFlow(bb, !includeNull).getState());
96+
result = TypeState.forSubtraction(bb, update, declaredType.getAssignableTypes(!includeNull));
9797
}
9898
}
9999
return result;
@@ -102,28 +102,32 @@ public TypeState filter(BigBang bb, TypeState update) {
102102
@Override
103103
protected void onInputSaturated(BigBang bb, TypeFlow<?> input) {
104104
if (isAssignable) {
105-
TypeFlow<?> sourceFlow = declaredType.getTypeFlow(bb, includeNull);
106-
107-
/*
108-
* First mark this flow as saturated, then swap it out at its uses/observers with its
109-
* declared type flow. Marking this flow as saturated first is important: if there are
110-
* any uses or observers *in-flight*, i.e., not yet registered at this point, trying to
111-
* swap-out will have no effect on those. However, if this flow is already marked as
112-
* saturated when the use or observer *lands*, even if that happens while/after
113-
* swapping-out, then the corresponding use or observer will be notified of its input
114-
* saturation. Otherwise it may neighter get the saturation signal OR get swapped-out.
115-
*
116-
* The downside in the later case is that the input/observer will lose the more precise
117-
* type information that swapping-out would have provided and will just use the more
118-
* conservative approximation, e.g., the target method declared type for invokes.
119-
*/
105+
/* Swap this flow out at its uses/observers with its declared type flow. */
120106
setSaturated();
121-
swapOut(bb, sourceFlow);
107+
swapOut(bb, declaredType.getTypeFlow(bb, includeNull));
122108
} else {
123109
super.onInputSaturated(bb, input);
124110
}
125111
}
126112

113+
@Override
114+
protected void notifyUseOfSaturation(BigBang bb, TypeFlow<?> use) {
115+
if (isAssignable) {
116+
swapAtUse(bb, declaredType.getTypeFlow(bb, includeNull), use);
117+
} else {
118+
super.notifyUseOfSaturation(bb, use);
119+
}
120+
}
121+
122+
@Override
123+
protected void notifyObserverOfSaturation(BigBang bb, TypeFlow<?> observer) {
124+
if (isAssignable) {
125+
swapAtObserver(bb, declaredType.getTypeFlow(bb, includeNull), observer);
126+
} else {
127+
super.notifyObserverOfSaturation(bb, observer);
128+
}
129+
}
130+
127131
@Override
128132
public boolean addState(BigBang bb, TypeState add) {
129133
assert this.isClone();

0 commit comments

Comments
 (0)