diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/ActualParameterTypeFlow.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/ActualParameterTypeFlow.java index a1588f806e8b..8e9cc09d8ac6 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/ActualParameterTypeFlow.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/ActualParameterTypeFlow.java @@ -32,7 +32,7 @@ * A sink type flow for the context insensitive invoke used to link in parameters in each caller * context. */ -public class ActualParameterTypeFlow extends TypeFlow { +public class ActualParameterTypeFlow extends TypeFlow implements GlobalFlow { public ActualParameterTypeFlow(AnalysisType declaredType) { super(null, filterUncheckedInterface(declaredType)); } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AllSynchronizedTypeFlow.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AllSynchronizedTypeFlow.java index 070cac7e318b..9642c69c8dea 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AllSynchronizedTypeFlow.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AllSynchronizedTypeFlow.java @@ -27,7 +27,7 @@ /** * Keeps track of all synchronized types. */ -public class AllSynchronizedTypeFlow extends TypeFlow { +public class AllSynchronizedTypeFlow extends TypeFlow implements GlobalFlow { @Override public String toString() { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/LocalAllInstantiatedFlow.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/LocalAllInstantiatedFlow.java index 36cdc016c2c0..2b10c3439013 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/LocalAllInstantiatedFlow.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/LocalAllInstantiatedFlow.java @@ -27,13 +27,15 @@ import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.meta.AnalysisType; +import jdk.vm.ci.code.BytecodePosition; + /** * A local use of AllInstantiatedFlow that can have a predicate. */ -public class LocalAllInstantiatedFlow extends TypeFlow { +public class LocalAllInstantiatedFlow extends TypeFlow { - public LocalAllInstantiatedFlow(AnalysisType declaredType) { - super(declaredType, declaredType); + public LocalAllInstantiatedFlow(BytecodePosition position, AnalysisType declaredType) { + super(position, declaredType); } private LocalAllInstantiatedFlow(MethodFlowsGraph methodFlows, LocalAllInstantiatedFlow original) { @@ -41,7 +43,7 @@ private LocalAllInstantiatedFlow(MethodFlowsGraph methodFlows, LocalAllInstantia } @Override - public TypeFlow copy(PointsToAnalysis bb, MethodFlowsGraph methodFlows) { + public TypeFlow copy(PointsToAnalysis bb, MethodFlowsGraph methodFlows) { return new LocalAllInstantiatedFlow(methodFlows, this); } } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodFlowsGraph.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodFlowsGraph.java index c6150609b526..c83de0531504 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodFlowsGraph.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodFlowsGraph.java @@ -43,6 +43,7 @@ import jdk.graal.compiler.graph.Node; import jdk.graal.compiler.nodes.EncodedGraph.EncodedNodeReference; +import jdk.vm.ci.code.BytecodePosition; public class MethodFlowsGraph implements MethodFlowsGraphInfo { /** @@ -124,7 +125,7 @@ public static boolean nonMethodFlow(TypeFlow flow) { * * AnyPrimitiveFlow can be either global (source == null) or local (source != null) */ - return flow instanceof AllInstantiatedTypeFlow || flow instanceof AllSynchronizedTypeFlow || (flow instanceof AnyPrimitiveSourceTypeFlow && flow.getSource() == null); + return flow instanceof GlobalFlow || flow.isContextInsensitive() || (flow instanceof AnyPrimitiveSourceTypeFlow && flow.getSource() == null); } /** @@ -224,10 +225,27 @@ public boolean hasNext() { @Override public TypeFlow next() { TypeFlow current = next; + assert withinMethod(current) : "Flow " + current + " has source " + current.source + " that is not a part of " + method; next = findNext(); return current; } + /** + * Check that the flow is local to the typeflow graph of this method. The iterator + * should not leave the scope of this method, but it may include flows originated from + * inlined methods. + */ + private boolean withinMethod(TypeFlow flow) { + var source = flow.getSource(); + while (source instanceof BytecodePosition position) { + if (method.equals(position.getMethod())) { + return true; + } + source = position.getCaller(); + } + return false; + } + /** Get the next flow and expand the work list. */ private TypeFlow findNext() { /* pollFirst returns null if the deque is empty. */ diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java index 8c6e75b6959d..5f61e0ac58c0 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java @@ -750,9 +750,9 @@ protected void apply(boolean forceReparse, Object reason) { * It only makes sense to create a local version of all instantiated if it will be guarded by a * predicate more precise than alwaysEnabled. */ - protected TypeFlow maybePatchAllInstantiated(TypeFlow flow, AnalysisType declaredType, Object predicate) { + protected TypeFlow maybePatchAllInstantiated(TypeFlow flow, BytecodePosition position, AnalysisType declaredType, Object predicate) { if (bb.usePredicates() && flow instanceof AllInstantiatedTypeFlow && predicate != alwaysEnabled) { - var localFlow = new LocalAllInstantiatedFlow(declaredType); + var localFlow = new LocalAllInstantiatedFlow(position, declaredType); flowsGraph.addMiscEntryFlow(localFlow); flow.addUse(bb, localFlow); return localFlow; @@ -818,13 +818,14 @@ protected TypeFlowBuilder handleObjectStamp(ObjectStamp stamp, ValueNode node throw AnalysisError.shouldNotReachHere("Stamp for node " + node + " is empty."); } AnalysisType stampType = (AnalysisType) StampTool.typeOrNull(stamp, bb.getMetaAccess()); + BytecodePosition position = AbstractAnalysisEngine.sourcePosition(node); if (stamp.isExactType()) { /* * We are lucky: the stamp tells us which type the node has. Happens e.g. for a * predicated boxed node. */ return TypeFlowBuilder.create(bb, method, getPredicate(), node, SourceTypeFlow.class, () -> { - SourceTypeFlow src = new SourceTypeFlow(AbstractAnalysisEngine.sourcePosition(node), stampType, !stamp.nonNull()); + SourceTypeFlow src = new SourceTypeFlow(position, stampType, !stamp.nonNull()); flowsGraph.addMiscEntryFlow(src); return src; }); @@ -835,9 +836,9 @@ protected TypeFlowBuilder handleObjectStamp(ObjectStamp stamp, ValueNode node */ TypeFlowBuilder predicate = getPredicate(); return TypeFlowBuilder.create(bb, method, predicate, node, TypeFlow.class, () -> { - TypeFlow proxy = bb.analysisPolicy().proxy(AbstractAnalysisEngine.sourcePosition(node), stampType.getTypeFlow(bb, true)); + TypeFlow proxy = bb.analysisPolicy().proxy(position, stampType.getTypeFlow(bb, true)); flowsGraph.addMiscEntryFlow(proxy); - return maybePatchAllInstantiated(proxy, stampType, predicate); + return maybePatchAllInstantiated(proxy, position, stampType, predicate); }); } } @@ -1470,9 +1471,10 @@ protected void node(FixedNode n) { TypeFlowBuilder exceptionObjectBuilder = TypeFlowBuilder.create(bb, method, predicate, node, TypeFlow.class, () -> { AnalysisType analysisType = (AnalysisType) StampTool.typeOrNull(node, bb.getMetaAccess()); TypeFlow input = analysisType.getTypeFlow(bb, false); - TypeFlow exceptionObjectFlow = bb.analysisPolicy().proxy(AbstractAnalysisEngine.sourcePosition(node), input); + BytecodePosition position = AbstractAnalysisEngine.sourcePosition(node); + TypeFlow exceptionObjectFlow = bb.analysisPolicy().proxy(position, input); flowsGraph.addMiscEntryFlow(exceptionObjectFlow); - return maybePatchAllInstantiated(exceptionObjectFlow, analysisType, predicate); + return maybePatchAllInstantiated(exceptionObjectFlow, position, analysisType, predicate); }); state.add(node, exceptionObjectBuilder); @@ -1533,7 +1535,7 @@ protected void node(FixedNode n) { instanceType = bb.getObjectType(); TypeFlowBuilder predicate = state.getPredicate(); instanceTypeBuilder = TypeFlowBuilder.create(bb, method, predicate, instanceType, TypeFlow.class, - () -> maybePatchAllInstantiated(instanceType.getTypeFlow(bb, false), instanceType, predicate)); + () -> maybePatchAllInstantiated(instanceType.getTypeFlow(bb, false), AbstractAnalysisEngine.sourcePosition(node), instanceType, predicate)); } TypeFlowBuilder dynamicNewInstanceBuilder = TypeFlowBuilder.create(bb, method, state.getPredicate(), node, DynamicNewInstanceTypeFlow.class, () -> { DynamicNewInstanceTypeFlow newInstanceTypeFlow = new DynamicNewInstanceTypeFlow(AbstractAnalysisEngine.sourcePosition(node), instanceTypeBuilder.get(), instanceType); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/StoreFieldTypeFlow.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/StoreFieldTypeFlow.java index 89287dee949b..1f602d9eee8a 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/StoreFieldTypeFlow.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/StoreFieldTypeFlow.java @@ -103,10 +103,10 @@ public String toString() { /** * The state of the StoreFieldTypeFlow reflects the state of the stored value. The * StoreFieldTypeFlow is an observer of the receiver flow, i.e. flow modeling the receiver - * object of the store operation.. + * object of the store operation. * * Every time the state of the receiver flow changes the corresponding field flows are added as - * uses to the store field flow. Thus the stored value is propagated to the store field flow + * uses to the store field flow. Thus, the stored value is propagated to the store field flow * into the field flows. */ public static class StoreInstanceFieldTypeFlow extends StoreFieldTypeFlow { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/flow/SVMMethodTypeFlowBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/flow/SVMMethodTypeFlowBuilder.java index e391d4fb58ff..f3b99ead980d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/flow/SVMMethodTypeFlowBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/flow/SVMMethodTypeFlowBuilder.java @@ -170,9 +170,10 @@ private void storeVMThreadLocal(TypeFlowsOfNodes state, ValueNode storeNode, Val TypeFlowBuilder predicate = state.getPredicate(); TypeFlowBuilder storeBuilder = TypeFlowBuilder.create(bb, method, predicate, storeNode, TypeFlow.class, () -> { - TypeFlow proxy = bb.analysisPolicy().proxy(AbstractAnalysisEngine.sourcePosition(storeNode), valueType.getTypeFlow(bb, false)); + BytecodePosition position = AbstractAnalysisEngine.sourcePosition(storeNode); + TypeFlow proxy = bb.analysisPolicy().proxy(position, valueType.getTypeFlow(bb, false)); flowsGraph.addMiscEntryFlow(proxy); - return maybePatchAllInstantiated(proxy, valueType, predicate); + return maybePatchAllInstantiated(proxy, position, valueType, predicate); }); storeBuilder.addUseDependency(valueBuilder); typeFlowGraphBuilder.registerSinkBuilder(storeBuilder);