Skip to content

Commit 93d285b

Browse files
committed
Make filter swap-out deterministic.
1 parent 4def538 commit 93d285b

File tree

5 files changed

+58
-28
lines changed

5 files changed

+58
-28
lines changed

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/flow/FieldFilterTypeFlow.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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/FilterTypeFlow.java

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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 neither 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();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public int position() {
7878
@Override
7979
public String toString() {
8080
StringBuilder str = new StringBuilder();
81-
str.append("FormalParamFlow").append("[").append(method.format("%H.%n")).append("]").append("[").append(position).append("]<").append(getState()).append(">");
81+
str.append("FormalParamFlow").append("[").append(method.format("%H.%n(%p)")).append("]").append("[").append(position).append("]<").append(getState()).append(">");
8282
return str.toString();
8383
}
8484

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

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public abstract class TypeFlow<T> {
9797
* the type flow graph.
9898
* <p/>
9999
* A type flow can also be marked as saturated when one of its inputs has reached the saturated
100-
* state and has propagated the "saturated" marker downstream. Thus, since in such a situtation
100+
* state and has propagated the "saturated" marker downstream. Thus, since in such a situation
101101
* the input stops propagating type states, a flow's type state may be incomplete. It is up to
102102
* individual type flows to subscribe themselves directly to the type flows of their declared
103103
* types if they need further updates.
@@ -354,7 +354,7 @@ public boolean addUse(BigBang bb, TypeFlow<?> use) {
354354
private boolean addUse(BigBang bb, TypeFlow<?> use, boolean propagateTypeState, boolean registerInput) {
355355
if (isSaturated() && propagateTypeState) {
356356
/* Let the use know that this flow is already saturated. */
357-
use.onInputSaturated(bb, this);
357+
notifyUseOfSaturation(bb, use);
358358
return false;
359359
}
360360
if (doAddUse(bb, use, registerInput)) {
@@ -366,7 +366,7 @@ private boolean addUse(BigBang bb, TypeFlow<?> use, boolean propagateTypeState,
366366
* use would have missed the saturated signal. Let the use know that this flow
367367
* became saturated.
368368
*/
369-
use.onInputSaturated(bb, this);
369+
notifyUseOfSaturation(bb, use);
370370
/* And unlink the use. */
371371
removeUse(use);
372372
return false;
@@ -379,6 +379,10 @@ private boolean addUse(BigBang bb, TypeFlow<?> use, boolean propagateTypeState,
379379
return false;
380380
}
381381

382+
protected void notifyUseOfSaturation(BigBang bb, TypeFlow<?> use) {
383+
use.onInputSaturated(bb, this);
384+
}
385+
382386
protected boolean doAddUse(BigBang bb, TypeFlow<?> use, boolean registerInput) {
383387
if (use.isSaturated()) {
384388
/* The use is already saturated so it will not be linked. */
@@ -416,14 +420,14 @@ public void addObserver(BigBang bb, TypeFlow<?> observer) {
416420
private boolean addObserver(BigBang bb, TypeFlow<?> observer, boolean triggerUpdate, boolean registerObservees) {
417421
if (isSaturated() && triggerUpdate) {
418422
/* Let the observer know that this flow is already saturated. */
419-
observer.onObservedSaturated(bb, this);
423+
notifyObserverOfSaturation(bb, observer);
420424
return false;
421425
}
422426
if (doAddObserver(bb, observer, registerObservees)) {
423427
if (triggerUpdate) {
424428
if (isSaturated()) {
425429
/* This flow is already saturated, notify the observer. */
426-
observer.onObservedSaturated(bb, this);
430+
notifyObserverOfSaturation(bb, observer);
427431
removeObserver(observer);
428432
return false;
429433
} else if (!this.state.isEmpty()) {
@@ -445,6 +449,10 @@ public void run(DebugContext ignore) {
445449
return false;
446450
}
447451

452+
protected void notifyObserverOfSaturation(BigBang bb, TypeFlow<?> observer) {
453+
observer.onObservedSaturated(bb, this);
454+
}
455+
448456
private boolean doAddObserver(BigBang bb, TypeFlow<?> observer, boolean registerObservees) {
449457
/*
450458
* An observer is linked even if it is already saturated itself, hence no
@@ -603,16 +611,24 @@ private void notifySaturated(BigBang bb) {
603611
/** This flow will swap itself out at all uses and observers. */
604612
protected void swapOut(BigBang bb, TypeFlow<?> newFlow) {
605613
for (TypeFlow<?> use : getUses()) {
606-
removeUse(use);
607-
newFlow.addUse(bb, use);
614+
swapAtUse(bb, newFlow, use);
608615
}
609616
for (TypeFlow<?> observer : getObservers()) {
610-
removeObserver(observer);
611-
/* Notify the observer that its observed flow has changed. */
612-
observer.replacedObservedWith(bb, newFlow);
617+
swapAtObserver(bb, newFlow, observer);
613618
}
614619
}
615620

621+
protected void swapAtUse(BigBang bb, TypeFlow<?> newFlow, TypeFlow<?> use) {
622+
removeUse(use);
623+
newFlow.addUse(bb, use);
624+
}
625+
626+
protected void swapAtObserver(BigBang bb, TypeFlow<?> newFlow, TypeFlow<?> observer) {
627+
removeObserver(observer);
628+
/* Notify the observer that its observed flow has changed. */
629+
observer.replacedObservedWith(bb, newFlow);
630+
}
631+
616632
/**
617633
* Notified by an input that it is saturated and it will stop sending updates.
618634
*/

0 commit comments

Comments
 (0)