Skip to content

Commit c4feee4

Browse files
committed
[GR-43722] Refactor method flows graph init.
PullRequest: graal/13674
2 parents cbe10bc + f92b1b0 commit c4feee4

18 files changed

+139
-68
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ public void forceUnsafeUpdate(AnalysisField field) {
181181
// force update of the unsafe loads
182182
for (AbstractUnsafeLoadTypeFlow unsafeLoad : unsafeLoads.keySet()) {
183183
/* Force update for unsafe accessed static fields. */
184-
unsafeLoad.initFlow(this);
184+
unsafeLoad.forceUpdate(this);
185185

186186
/*
187187
* Force update for unsafe accessed instance fields: post the receiver object flow for
@@ -194,7 +194,7 @@ public void forceUnsafeUpdate(AnalysisField field) {
194194
// force update of the unsafe stores
195195
for (AbstractUnsafeStoreTypeFlow unsafeStore : unsafeStores.keySet()) {
196196
/* Force update for unsafe accessed static fields. */
197-
unsafeStore.initFlow(this);
197+
unsafeStore.forceUpdate(this);
198198

199199
/*
200200
* Force update for unsafe accessed instance fields: post the receiver object flow for

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@ protected AbstractStaticInvokeTypeFlow(PointsToAnalysis bb, MethodFlowsGraph met
4141
super(bb, methodFlows, original);
4242
}
4343

44+
@Override
45+
public void initFlow(PointsToAnalysis bb) {
46+
/* Trigger the update for static invokes, there is no receiver to trigger it. */
47+
bb.postFlow(this);
48+
}
49+
50+
@Override
51+
public boolean needsInitialization() {
52+
return true;
53+
}
54+
4455
@Override
4556
public String toString() {
4657
return "StaticInvoke<" + targetMethod.format("%h.%n") + ">" + ":" + getState();

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
package com.oracle.graal.pointsto.flow;
2626

2727
import java.util.Collection;
28+
import java.util.List;
2829
import java.util.concurrent.ConcurrentHashMap;
2930
import java.util.concurrent.ConcurrentMap;
3031

@@ -81,7 +82,7 @@ public MethodFlowsGraphInfo addContext(PointsToAnalysis bb, AnalysisContext call
8182
}
8283

8384
@Override
84-
protected void initFlowsGraph(PointsToAnalysis bb) {
85+
protected void initFlowsGraph(PointsToAnalysis bb, List<TypeFlow<?>> postInitFlows) {
8586
// nothing to do, cloning does all the initialization
8687
}
8788

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ public void initFlow(PointsToAnalysis bb) {
6666
addState(bb, constantState);
6767
}
6868

69+
@Override
70+
public boolean needsInitialization() {
71+
return true;
72+
}
73+
6974
@Override
7075
public String toString() {
7176
return "ConstantFlow<" + getState() + ">";

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ public void initFlow(PointsToAnalysis bb) {
7070
this.newTypeFlow.addObserver(bb, this);
7171
}
7272

73+
@Override
74+
public boolean needsInitialization() {
75+
return true;
76+
}
77+
7378
@Override
7479
public void onObservedUpdate(PointsToAnalysis bb) {
7580
/* The state of the new type provider has changed. */

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

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@ protected void updateReceiver(PointsToAnalysis bb, MethodFlowsGraphInfo calleeFl
183183
if (bb.optimizeReturnedParameter()) {
184184
int paramIndex = calleeFlows.getMethod().getTypeFlow().getReturnedParameterIndex();
185185
if (actualReturn != null && paramIndex == 0) {
186+
/*
187+
* The callee returns `this`. Propagate the receiver state to the actual-return.
188+
* See also InvokeTypeFlow#linkReturn() for more details.
189+
*/
186190
actualReturn.addState(bb, receiverTypeState);
187191
}
188192
}
@@ -240,10 +244,21 @@ public void linkReturn(PointsToAnalysis bb, boolean isStatic, MethodFlowsGraphIn
240244
if (isStatic || paramNodeIndex != 0) {
241245
TypeFlow<?> actualParam = actualParameters[paramNodeIndex];
242246
actualParam.addUse(bb, actualReturn);
247+
} else {
248+
/*
249+
* The callee returns `this`. The formal-receiver state is updated in
250+
* InvokeTypeFlow#updateReceiver() for each linked callee and every time
251+
* the formal-receiver is updated then the same update state is
252+
* propagated to the actual-return. One may think that we could simply
253+
* add a direct use link from the formal-receiver in the callee to the
254+
* actual-return in the caller to get the state propagation
255+
* automatically. But that would be wrong because then the actual-return
256+
* would get the state from *all* the other places that callee may be
257+
* called from, and that would defeat the purpose of this optimization:
258+
* we want just the receiver state from the caller of current invoke to
259+
* reach the actual-return.
260+
*/
243261
}
244-
// else {
245-
// receiver object state is transferred in updateReceiver()
246-
// }
247262
} else {
248263
/*
249264
* The callee may have a return type, hence the actualReturn is non-null,

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ public void initFlow(PointsToAnalysis bb) {
7474
fieldFlow.addUse(bb, this);
7575
}
7676

77+
@Override
78+
public boolean needsInitialization() {
79+
return true;
80+
}
81+
7782
@Override
7883
public String toString() {
7984
return "LoadStaticFieldTypeFlow<" + getState() + ">";

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

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@
4141
import org.graalvm.compiler.nodes.EncodedGraph.EncodedNodeReference;
4242

4343
import com.oracle.graal.pointsto.PointsToAnalysis;
44-
import com.oracle.graal.pointsto.flow.OffsetLoadTypeFlow.AbstractUnsafeLoadTypeFlow;
45-
import com.oracle.graal.pointsto.flow.OffsetStoreTypeFlow.AbstractUnsafeStoreTypeFlow;
4644
import com.oracle.graal.pointsto.meta.AnalysisMethod;
4745
import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod;
4846
import com.oracle.graal.pointsto.util.AnalysisError;
@@ -113,28 +111,6 @@ public <T extends TypeFlow<?>> T lookupCloneOf(@SuppressWarnings("unused") Point
113111
return original;
114112
}
115113

116-
public void init(final PointsToAnalysis bb) {
117-
for (TypeFlow<?> flow : flows()) {
118-
if (flow instanceof AbstractUnsafeLoadTypeFlow) {
119-
bb.registerUnsafeLoad((AbstractUnsafeLoadTypeFlow) flow);
120-
}
121-
if (flow instanceof AbstractUnsafeStoreTypeFlow) {
122-
bb.registerUnsafeStore((AbstractUnsafeStoreTypeFlow) flow);
123-
}
124-
125-
/*
126-
* Run initialization code for corner case type flows. This can be used to add link from
127-
* 'outside' into the graph.
128-
*/
129-
flow.initFlow(bb);
130-
131-
/* Trigger the update for static invokes, there is no receiver to trigger it. */
132-
if (flow instanceof AbstractStaticInvokeTypeFlow) {
133-
bb.postFlow(flow);
134-
}
135-
}
136-
}
137-
138114
protected static boolean nonCloneableFlow(TypeFlow<?> flow) {
139115
/*
140116
* References to field flows and to array elements flows are not part of the method itself;

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

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,6 @@ private <V extends TypeFlow<?>> List<V> lookupClonesOf(PointsToAnalysis bb, List
120120
return result;
121121
}
122122

123-
@Override
124-
public void init(final PointsToAnalysis bb) {
125-
// the cloning mechanism does all the initialization
126-
throw AnalysisError.shouldNotReachHere();
127-
}
128-
129123
@Override
130124
@SuppressWarnings("unchecked")
131125
public <T extends TypeFlow<?>> T lookupCloneOf(PointsToAnalysis bb, T original) {
@@ -175,7 +169,9 @@ void linkCloneFlows(final PointsToAnalysis bb) {
175169
* Run initialization code for corner case type flows. This can be used to add link from
176170
* 'outside' into the graph.
177171
*/
178-
clone.initFlow(bb);
172+
if (clone.needsInitialization()) {
173+
clone.initFlow(bb);
174+
}
179175

180176
/* Link all 'internal' observers. */
181177
for (TypeFlow<?> originalObserver : original.getObservers()) {
@@ -210,12 +206,6 @@ void linkCloneFlows(final PointsToAnalysis bb) {
210206
clone.addUse(bb, clonedUse);
211207
}
212208
}
213-
214-
if (clone instanceof AbstractStaticInvokeTypeFlow) {
215-
/* Trigger the update for static invokes, there is no receiver to trigger it. */
216-
AbstractStaticInvokeTypeFlow invokeFlow = (AbstractStaticInvokeTypeFlow) clone;
217-
bb.postFlow(invokeFlow);
218-
}
219209
}
220210
}
221211

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

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.graalvm.compiler.nodes.ValueNode;
4040

4141
import com.oracle.graal.pointsto.PointsToAnalysis;
42+
import com.oracle.graal.pointsto.flow.builder.TypeFlowGraphBuilder;
4243
import com.oracle.graal.pointsto.meta.AnalysisMethod;
4344
import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod;
4445
import com.oracle.graal.pointsto.typestate.TypeState;
@@ -171,7 +172,7 @@ private synchronized void createFlowsGraph(PointsToAnalysis bb, InvokeTypeFlow r
171172
flowsGraph = builder.flowsGraph;
172173
assert flowsGraph != null;
173174

174-
initFlowsGraph(bb);
175+
initFlowsGraph(bb, builder.postInitFlows);
175176
} catch (Throwable t) {
176177
/* Wrap all other errors as parsing errors. */
177178
throw AnalysisError.parsingError(method, t);
@@ -200,8 +201,18 @@ private static int computeReturnedParameterIndex(StructuredGraph graph) {
200201
}
201202
}
202203

203-
protected void initFlowsGraph(PointsToAnalysis bb) {
204-
flowsGraph.init(bb);
204+
/**
205+
* Run type flow initialization. This will trigger state propagation from source flows, link
206+
* static load/store field flows, publish unsafe load/store flows, etc. The flows that need
207+
* initialization are collected by {@link TypeFlowGraphBuilder#build()}. Their initialization
208+
* needs to be triggered only after the graph is fully materialized such that lazily constructed
209+
* type flows (like InovkeTypeFlow.actualReturn) can observe the type state that other flows may
210+
* generate on initialization.
211+
*/
212+
protected void initFlowsGraph(PointsToAnalysis bb, List<TypeFlow<?>> postInitFlows) {
213+
for (TypeFlow<?> flow : postInitFlows) {
214+
flow.initFlow(bb);
215+
}
205216
}
206217

207218
public Collection<MethodFlowsGraph> getFlows() {
@@ -318,7 +329,7 @@ public synchronized boolean updateFlowsGraph(PointsToAnalysis bb, MethodFlowsGra
318329

319330
flowsGraph.updateInternalState(newGraphKind);
320331

321-
initFlowsGraph(bb);
332+
initFlowsGraph(bb, builder.postInitFlows);
322333

323334
if (registerAsImplementationInvoked) {
324335
if (parsingReason == null) {

0 commit comments

Comments
 (0)