Skip to content

Commit 7f11471

Browse files
committed
Make filter swap-out deterministic.
1 parent eea2a66 commit 7f11471

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.
@@ -358,7 +358,7 @@ public boolean addUse(BigBang bb, TypeFlow<?> use) {
358358
private boolean addUse(BigBang bb, TypeFlow<?> use, boolean propagateTypeState, boolean registerInput) {
359359
if (isSaturated() && propagateTypeState) {
360360
/* Let the use know that this flow is already saturated. */
361-
use.onInputSaturated(bb, this);
361+
notifyUseOfSaturation(bb, use);
362362
return false;
363363
}
364364
if (doAddUse(bb, use, registerInput)) {
@@ -370,7 +370,7 @@ private boolean addUse(BigBang bb, TypeFlow<?> use, boolean propagateTypeState,
370370
* use would have missed the saturated signal. Let the use know that this flow
371371
* became saturated.
372372
*/
373-
use.onInputSaturated(bb, this);
373+
notifyUseOfSaturation(bb, use);
374374
/* And unlink the use. */
375375
removeUse(use);
376376
return false;
@@ -383,6 +383,10 @@ private boolean addUse(BigBang bb, TypeFlow<?> use, boolean propagateTypeState,
383383
return false;
384384
}
385385

386+
protected void notifyUseOfSaturation(BigBang bb, TypeFlow<?> use) {
387+
use.onInputSaturated(bb, this);
388+
}
389+
386390
protected boolean doAddUse(BigBang bb, TypeFlow<?> use, boolean registerInput) {
387391
if (use.isSaturated()) {
388392
/* The use is already saturated so it will not be linked. */
@@ -420,14 +424,14 @@ public void addObserver(BigBang bb, TypeFlow<?> observer) {
420424
private boolean addObserver(BigBang bb, TypeFlow<?> observer, boolean triggerUpdate, boolean registerObservees) {
421425
if (isSaturated() && triggerUpdate) {
422426
/* Let the observer know that this flow is already saturated. */
423-
observer.onObservedSaturated(bb, this);
427+
notifyObserverOfSaturation(bb, observer);
424428
return false;
425429
}
426430
if (doAddObserver(bb, observer, registerObservees)) {
427431
if (triggerUpdate) {
428432
if (isSaturated()) {
429433
/* This flow is already saturated, notify the observer. */
430-
observer.onObservedSaturated(bb, this);
434+
notifyObserverOfSaturation(bb, observer);
431435
removeObserver(observer);
432436
return false;
433437
} else if (!this.state.isEmpty()) {
@@ -449,6 +453,10 @@ public void run(DebugContext ignore) {
449453
return false;
450454
}
451455

456+
protected void notifyObserverOfSaturation(BigBang bb, TypeFlow<?> observer) {
457+
observer.onObservedSaturated(bb, this);
458+
}
459+
452460
private boolean doAddObserver(BigBang bb, TypeFlow<?> observer, boolean registerObservees) {
453461
/*
454462
* An observer is linked even if it is already saturated itself, hence no
@@ -607,16 +615,24 @@ private void notifySaturated(BigBang bb) {
607615
/** This flow will swap itself out at all uses and observers. */
608616
protected void swapOut(BigBang bb, TypeFlow<?> newFlow) {
609617
for (TypeFlow<?> use : getUses()) {
610-
removeUse(use);
611-
newFlow.addUse(bb, use);
618+
swapAtUse(bb, newFlow, use);
612619
}
613620
for (TypeFlow<?> observer : getObservers()) {
614-
removeObserver(observer);
615-
/* Notify the observer that its observed flow has changed. */
616-
observer.replacedObservedWith(bb, newFlow);
621+
swapAtObserver(bb, newFlow, observer);
617622
}
618623
}
619624

625+
protected void swapAtUse(BigBang bb, TypeFlow<?> newFlow, TypeFlow<?> use) {
626+
removeUse(use);
627+
newFlow.addUse(bb, use);
628+
}
629+
630+
protected void swapAtObserver(BigBang bb, TypeFlow<?> newFlow, TypeFlow<?> observer) {
631+
removeObserver(observer);
632+
/* Notify the observer that its observed flow has changed. */
633+
observer.replacedObservedWith(bb, newFlow);
634+
}
635+
620636
/**
621637
* Notified by an input that it is saturated and it will stop sending updates.
622638
*/

0 commit comments

Comments
 (0)