Skip to content

Commit af88c71

Browse files
committed
Lazily remove invalid typesflows from analysis.
1 parent e578fde commit af88c71

File tree

3 files changed

+47
-3
lines changed

3 files changed

+47
-3
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,9 @@ public void run(DebugContext ignored) {
487487
PointsToStats.registerTypeFlowQueuedUpdate(PointsToAnalysis.this, operation);
488488

489489
operation.inQueue = false;
490-
operation.update(PointsToAnalysis.this);
490+
if (operation.isValid()) {
491+
operation.update(PointsToAnalysis.this);
492+
}
491493
}
492494

493495
@Override

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,15 @@ public String toString() {
468468
*/
469469
final void removeInternalFlows(PointsToAnalysis bb) {
470470

471+
// Invalidate internal flows which will be cleared
472+
flowsIterator().forEachRemaining(typeFlow -> {
473+
// param and return flows will not be cleared
474+
boolean skipInvalidate = typeFlow instanceof FormalParamTypeFlow || typeFlow instanceof FormalReturnTypeFlow;
475+
if (!skipInvalidate) {
476+
typeFlow.invalidate();
477+
}
478+
});
479+
471480
// Clear out the parameter uses and observers
472481
for (var param : getParameters()) {
473482
if (param != null) {

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

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ public abstract class TypeFlow<T> {
104104
*/
105105
private volatile boolean isSaturated;
106106

107+
/**
108+
* A TypeFlow is invalidated when the flowsgraph it belongs to is updated due to
109+
* {@link MethodTypeFlow#updateFlowsGraph}. Once a flow is invalided it no longer needs to be
110+
* updated and its links can be removed. Note delaying the removal of invalid flows does not
111+
* affect correctness, so they can be removed lazily.
112+
*/
113+
private boolean isValid = true;
114+
107115
@SuppressWarnings("rawtypes")//
108116
private static final AtomicReferenceFieldUpdater<TypeFlow, TypeState> STATE_UPDATER = AtomicReferenceFieldUpdater.newUpdater(TypeFlow.class, TypeState.class, "state");
109117

@@ -258,6 +266,20 @@ public int getSlot() {
258266
return this.slot;
259267
}
260268

269+
/**
270+
* Return true is the flow is valid and should be updated.
271+
*/
272+
public boolean isValid() {
273+
return isValid;
274+
}
275+
276+
/**
277+
* Invalidating the typeflow will cause the flow to be lazily removed in the future.
278+
*/
279+
public void invalidate() {
280+
isValid = false;
281+
}
282+
261283
/**
262284
* Return true if this flow is saturated. When an observer becomes saturated it doesn't
263285
* immediately remove itself from all its inputs. The inputs lazily remove it on next update.
@@ -392,6 +414,9 @@ protected boolean doAddUse(PointsToAnalysis bb, TypeFlow<?> use) {
392414
if (use.equals(this)) {
393415
return false;
394416
}
417+
if (!use.isValid()) {
418+
return false;
419+
}
395420
/* Input is always tracked. */
396421
registerInput(bb, use);
397422
if (use.isSaturated()) {
@@ -473,6 +498,10 @@ private boolean doAddObserver(PointsToAnalysis bb, TypeFlow<?> observer) {
473498
if (observer.equals(this)) {
474499
return false;
475500
}
501+
if (!observer.isValid()) {
502+
return false;
503+
}
504+
476505
registerObservee(bb, observer);
477506
return ConcurrentLightHashSet.addElement(this, OBSERVERS_UPDATER, observer);
478507
}
@@ -579,15 +608,19 @@ public static AnalysisType filterUncheckedInterface(AnalysisType type) {
579608
public void update(PointsToAnalysis bb) {
580609
TypeState curState = getState();
581610
for (TypeFlow<?> use : getUses()) {
582-
if (use.isSaturated()) {
611+
if (!use.isValid() || use.isSaturated()) {
583612
removeUse(use);
584613
} else {
585614
use.addState(bb, curState);
586615
}
587616
}
588617

589618
for (TypeFlow<?> observer : getObservers()) {
590-
observer.onObservedUpdate(bb);
619+
if (observer.isValid()) {
620+
observer.onObservedUpdate(bb);
621+
} else {
622+
removeObserver(observer);
623+
}
591624
}
592625
}
593626

0 commit comments

Comments
 (0)