Skip to content

Commit 9a1ebd0

Browse files
committed
[GR-38711] Remove clones for default points-to analysis.
PullRequest: graal/11786
2 parents 8814fd3 + 4ad2a38 commit 9a1ebd0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1704
-1231
lines changed

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

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,15 @@
3030

3131
import com.oracle.graal.pointsto.api.PointstoOptions;
3232
import com.oracle.graal.pointsto.flow.AbstractSpecialInvokeTypeFlow;
33+
import com.oracle.graal.pointsto.flow.AbstractStaticInvokeTypeFlow;
3334
import com.oracle.graal.pointsto.flow.AbstractVirtualInvokeTypeFlow;
3435
import com.oracle.graal.pointsto.flow.ActualReturnTypeFlow;
3536
import com.oracle.graal.pointsto.flow.CloneTypeFlow;
37+
import com.oracle.graal.pointsto.flow.InvokeTypeFlow;
38+
import com.oracle.graal.pointsto.flow.MethodFlowsGraph;
39+
import com.oracle.graal.pointsto.flow.MethodTypeFlow;
3640
import com.oracle.graal.pointsto.flow.TypeFlow;
3741
import com.oracle.graal.pointsto.flow.context.AnalysisContext;
38-
import com.oracle.graal.pointsto.flow.context.AnalysisContextPolicy;
3942
import com.oracle.graal.pointsto.flow.context.BytecodeLocation;
4043
import com.oracle.graal.pointsto.flow.context.object.AnalysisObject;
4144
import com.oracle.graal.pointsto.meta.AnalysisField;
@@ -89,13 +92,7 @@ public int typeFlowSaturationCutoff() {
8992
return typeFlowSaturationCutoff;
9093
}
9194

92-
/** Provide an analysis context policy. */
93-
protected abstract AnalysisContextPolicy<? extends AnalysisContext> contextPolicy();
94-
95-
@SuppressWarnings("unchecked")
96-
public AnalysisContextPolicy<AnalysisContext> getContextPolicy() {
97-
return (AnalysisContextPolicy<AnalysisContext>) contextPolicy();
98-
}
95+
public abstract MethodTypeFlow createMethodTypeFlow(PointsToAnalysisMethod method);
9996

10097
/**
10198
* Specifies if this policy models constants objects context sensitively, i.e., by creating a
@@ -159,10 +156,28 @@ public BytecodeLocation createAllocationSite(PointsToAnalysis bb, Object key, An
159156
public abstract AbstractVirtualInvokeTypeFlow createVirtualInvokeTypeFlow(BytecodePosition invokeLocation, AnalysisType receiverType, PointsToAnalysisMethod targetMethod,
160157
TypeFlow<?>[] actualParameters, ActualReturnTypeFlow actualReturn, BytecodeLocation location);
161158

162-
/** Provides implementation for the virtual invoke type flow. */
159+
/** Provides implementation for the special invoke type flow. */
163160
public abstract AbstractSpecialInvokeTypeFlow createSpecialInvokeTypeFlow(BytecodePosition invokeLocation, AnalysisType receiverType, PointsToAnalysisMethod targetMethod,
164161
TypeFlow<?>[] actualParameters, ActualReturnTypeFlow actualReturn, BytecodeLocation location);
165162

163+
/** Provides implementation for the static invoke type flow. */
164+
public abstract AbstractStaticInvokeTypeFlow createStaticInvokeTypeFlow(BytecodePosition invokeLocation, AnalysisType receiverType, PointsToAnalysisMethod targetMethod,
165+
TypeFlow<?>[] actualParameters, ActualReturnTypeFlow actualReturn, BytecodeLocation location);
166+
167+
public abstract MethodFlowsGraph staticRootMethodGraph(PointsToAnalysis bb, PointsToAnalysisMethod pointsToMethod);
168+
169+
public abstract AnalysisContext allocationContext(PointsToAnalysis bb, MethodFlowsGraph callerGraph);
170+
171+
public abstract TypeFlow<?> proxy(BytecodePosition source, TypeFlow<?> input);
172+
173+
public abstract boolean addOriginalUse(PointsToAnalysis bb, TypeFlow<?> flow, TypeFlow<?> use);
174+
175+
public abstract boolean addOriginalObserver(PointsToAnalysis bb, TypeFlow<?> flow, TypeFlow<?> observer);
176+
177+
public abstract void linkActualReturn(PointsToAnalysis bb, boolean isStatic, InvokeTypeFlow invoke);
178+
179+
public abstract void registerAsImplementationInvoked(InvokeTypeFlow invoke, MethodFlowsGraph calleeFlows);
180+
166181
@SuppressWarnings("unused")
167182
public int makeProperties(BigBang bb, AnalysisObject... objects) {
168183
/* The default analysis policy doesn't use properties. */
@@ -244,5 +259,4 @@ public final TypeState doSubtraction(PointsToAnalysis bb, SingleTypeState s1, Mu
244259
public abstract TypeState doSubtraction(PointsToAnalysis bb, MultiTypeState s1, SingleTypeState s2);
245260

246261
public abstract TypeState doSubtraction(PointsToAnalysis bb, MultiTypeState s1, MultiTypeState s2);
247-
248262
}

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

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@
6868
import com.oracle.graal.pointsto.flow.OffsetLoadTypeFlow.AbstractUnsafeLoadTypeFlow;
6969
import com.oracle.graal.pointsto.flow.OffsetStoreTypeFlow.AbstractUnsafeStoreTypeFlow;
7070
import com.oracle.graal.pointsto.flow.TypeFlow;
71-
import com.oracle.graal.pointsto.flow.context.AnalysisContext;
72-
import com.oracle.graal.pointsto.flow.context.AnalysisContextPolicy;
7371
import com.oracle.graal.pointsto.infrastructure.WrappedSignature;
7472
import com.oracle.graal.pointsto.meta.AnalysisField;
7573
import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
@@ -267,7 +265,7 @@ public void forceUnsafeUpdate(AnalysisField field) {
267265
// force update of the unsafe loads
268266
for (AbstractUnsafeLoadTypeFlow unsafeLoad : unsafeLoads.keySet()) {
269267
/* Force update for unsafe accessed static fields. */
270-
unsafeLoad.initClone(this);
268+
unsafeLoad.initFlow(this);
271269

272270
/*
273271
* Force update for unsafe accessed instance fields: post the receiver object flow for
@@ -280,7 +278,7 @@ public void forceUnsafeUpdate(AnalysisField field) {
280278
// force update of the unsafe stores
281279
for (AbstractUnsafeStoreTypeFlow unsafeStore : unsafeStores.keySet()) {
282280
/* Force update for unsafe accessed static fields. */
283-
unsafeStore.initClone(this);
281+
unsafeStore.initFlow(this);
284282

285283
/*
286284
* Force update for unsafe accessed instance fields: post the receiver object flow for
@@ -334,10 +332,6 @@ public AnalysisPolicy analysisPolicy() {
334332
return analysisPolicy;
335333
}
336334

337-
public AnalysisContextPolicy<AnalysisContext> contextPolicy() {
338-
return analysisPolicy.getContextPolicy();
339-
}
340-
341335
@Override
342336
public AnalysisUniverse getUniverse() {
343337
return universe;
@@ -462,8 +456,7 @@ public AnalysisMethod addRootMethod(AnalysisMethod aMethod, boolean invokeSpecia
462456
postTask(() -> {
463457
pointsToMethod.registerAsDirectRootMethod();
464458
pointsToMethod.registerAsImplementationInvoked(null);
465-
MethodTypeFlow methodFlow = pointsToMethod.getTypeFlow();
466-
MethodFlowsGraph methodFlowsGraph = methodFlow.addContext(PointsToAnalysis.this, PointsToAnalysis.this.contextPolicy().emptyContext());
459+
MethodFlowsGraph methodFlowsGraph = analysisPolicy.staticRootMethodGraph(this, pointsToMethod);
467460
for (int idx = 0; idx < paramCount; idx++) {
468461
AnalysisType declaredParamType = (AnalysisType) signature.getParameterType(idx, declaringClass);
469462
FormalParamTypeFlow parameter = methodFlowsGraph.getParameter(idx);

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ protected void initCallee() {
7575

7676
@Override
7777
public void onObservedSaturated(PointsToAnalysis bb, TypeFlow<?> observed) {
78-
assert this.isClone();
7978
/* When the receiver flow saturates start observing the flow of the receiver type. */
8079
replaceObservedWith(bb, receiverType);
8180
}
Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -24,25 +24,25 @@
2424
*/
2525
package com.oracle.graal.pointsto.flow;
2626

27-
import org.graalvm.compiler.graph.Node;
27+
import com.oracle.graal.pointsto.PointsToAnalysis;
28+
import com.oracle.graal.pointsto.flow.context.BytecodeLocation;
29+
import com.oracle.graal.pointsto.meta.AnalysisType;
30+
import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod;
2831

29-
/**
30-
* Models the ExceptionObjectNode. It is a proxy type flow, i.e., it propagates the state of its
31-
* input, which in current implementation is the type flow of a sub-type of Throwable.
32-
*/
33-
public class ExceptionObjectTypeFlow extends ProxyTypeFlow {
32+
import jdk.vm.ci.code.BytecodePosition;
3433

35-
public ExceptionObjectTypeFlow(Node source, TypeFlow<?> input) {
36-
super(source, input);
34+
public abstract class AbstractStaticInvokeTypeFlow extends DirectInvokeTypeFlow {
35+
protected AbstractStaticInvokeTypeFlow(BytecodePosition invokeLocation, AnalysisType receiverType, PointsToAnalysisMethod targetMethod,
36+
TypeFlow<?>[] actualParameters, ActualReturnTypeFlow actualReturn, BytecodeLocation location) {
37+
super(invokeLocation, receiverType, targetMethod, actualParameters, actualReturn, location);
3738
}
3839

39-
@Override
40-
public boolean canSaturate() {
41-
return false;
40+
protected AbstractStaticInvokeTypeFlow(PointsToAnalysis bb, MethodFlowsGraph methodFlows, AbstractStaticInvokeTypeFlow original) {
41+
super(bb, methodFlows, original);
4242
}
4343

4444
@Override
4545
public String toString() {
46-
return "ExceptionObjectFlow<" + input + ">";
46+
return "StaticInvoke<" + targetMethod.format("%h.%n") + ">" + ":" + getState();
4747
}
4848
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ public TypeFlow<BytecodePosition> copy(PointsToAnalysis bb, MethodFlowsGraph met
6666

6767
@Override
6868
public void onObservedUpdate(PointsToAnalysis bb) {
69-
assert this.isClone();
7069
if (bb.analysisPolicy().aliasArrayTypeFlows()) {
7170
/* All arrays are aliased, no need to model the array copy operation. */
7271
return;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.graal.pointsto.flow;
26+
27+
import java.util.Collection;
28+
import java.util.concurrent.ConcurrentHashMap;
29+
import java.util.concurrent.ConcurrentMap;
30+
31+
import org.graalvm.compiler.options.OptionValues;
32+
33+
import com.oracle.graal.pointsto.PointsToAnalysis;
34+
import com.oracle.graal.pointsto.api.PointstoOptions;
35+
import com.oracle.graal.pointsto.flow.context.AnalysisContext;
36+
import com.oracle.graal.pointsto.flow.context.bytecode.BytecodeAnalysisContext;
37+
import com.oracle.graal.pointsto.flow.context.bytecode.BytecodeAnalysisContextPolicy;
38+
import com.oracle.graal.pointsto.flow.context.bytecode.BytecodeSensitiveAnalysisPolicy;
39+
import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod;
40+
import com.oracle.graal.pointsto.typestate.TypeState;
41+
42+
public class CallSiteSensitiveMethodTypeFlow extends MethodTypeFlow {
43+
44+
private final ConcurrentMap<AnalysisContext, MethodFlowsGraph> clonedMethodFlows;
45+
private final int localCallingContextDepth;
46+
47+
public CallSiteSensitiveMethodTypeFlow(OptionValues options, PointsToAnalysisMethod method) {
48+
super(method);
49+
this.localCallingContextDepth = PointstoOptions.MaxCallingContextDepth.getValue(options);
50+
this.clonedMethodFlows = new ConcurrentHashMap<>(4, 0.75f, 1);
51+
}
52+
53+
/**
54+
* Add the context, if not already added, and return the method flows clone from that context.
55+
*/
56+
public MethodFlowsGraph addContext(PointsToAnalysis bb, AnalysisContext calleeContext) {
57+
return addContext(bb, calleeContext, null);
58+
}
59+
60+
public MethodFlowsGraph addContext(PointsToAnalysis bb, AnalysisContext calleeContext, InvokeTypeFlow reason) {
61+
62+
/* Ensure that the method is parsed before attempting to clone it. */
63+
this.ensureFlowsGraphCreated(bb, reason);
64+
this.getMethodFlowsGraph().ensureLinearized();
65+
66+
BytecodeAnalysisContextPolicy contextPolicy = ((BytecodeSensitiveAnalysisPolicy) bb.analysisPolicy()).getContextPolicy();
67+
AnalysisContext newContext = contextPolicy.peel((BytecodeAnalysisContext) calleeContext, localCallingContextDepth);
68+
69+
MethodFlowsGraphClone methodFlows = (MethodFlowsGraphClone) clonedMethodFlows.get(newContext);
70+
if (methodFlows == null) {
71+
MethodFlowsGraphClone newFlows = new MethodFlowsGraphClone(method, newContext);
72+
newFlows.cloneOriginalFlows(bb);
73+
MethodFlowsGraphClone oldFlows = (MethodFlowsGraphClone) clonedMethodFlows.putIfAbsent(newContext, newFlows);
74+
methodFlows = oldFlows != null ? oldFlows : newFlows;
75+
if (oldFlows == null) {
76+
/*
77+
* Link uses only the clone is registered since linking uses may trigger updates to
78+
* the current method in the current context.
79+
*/
80+
methodFlows.linkClones(bb);
81+
}
82+
}
83+
84+
return methodFlows;
85+
}
86+
87+
@Override
88+
protected void initFlowsGraph(PointsToAnalysis bb) {
89+
// nothing to do, cloning does all the initialization
90+
}
91+
92+
public int getLocalCallingContextDepth() {
93+
return localCallingContextDepth;
94+
}
95+
96+
@Override
97+
public Collection<MethodFlowsGraph> getFlows() {
98+
return clonedMethodFlows.values();
99+
}
100+
101+
public MethodFlowsGraph getFlows(AnalysisContext calleeContext) {
102+
return clonedMethodFlows.get(calleeContext);
103+
}
104+
105+
/**
106+
* Get a type state containing the union of states over all the clones of the original flow.
107+
*
108+
* @param originalTypeFlow the original type flow
109+
* @return the resulting type state object
110+
*/
111+
@Override
112+
public TypeState foldTypeFlow(PointsToAnalysis bb, TypeFlow<?> originalTypeFlow) {
113+
if (originalTypeFlow == null) {
114+
return null;
115+
}
116+
117+
TypeState result = TypeState.forEmpty();
118+
for (MethodFlowsGraph methodFlows : clonedMethodFlows.values()) {
119+
TypeFlow<?> clonedTypeFlow = methodFlows.lookupCloneOf(bb, originalTypeFlow);
120+
TypeState cloneState = clonedTypeFlow.getState();
121+
/*
122+
* Make a shallow copy of the clone state, i.e., only the types and not the concrete
123+
* objects, so that the union operation doesn't merge the concrete objects with abstract
124+
* objects.
125+
*/
126+
TypeState cloneStateCopy = bb.analysisPolicy().forContextInsensitiveTypeState(bb, cloneState);
127+
result = TypeState.forUnion(bb, result, cloneStateCopy);
128+
}
129+
return result;
130+
}
131+
132+
/** Check if the type flow is saturated, i.e., any of its clones is saturated. */
133+
@Override
134+
public boolean isSaturated(PointsToAnalysis bb, TypeFlow<?> originalTypeFlow) {
135+
boolean saturated = false;
136+
for (MethodFlowsGraph methodFlows : clonedMethodFlows.values()) {
137+
TypeFlow<?> clonedTypeFlow = methodFlows.lookupCloneOf(bb, originalTypeFlow);
138+
saturated |= clonedTypeFlow.isSaturated();
139+
}
140+
return saturated;
141+
}
142+
143+
@Override
144+
public String toString() {
145+
return "CallSiteSensitiveMethodTypeFlow<" + method + ">";
146+
}
147+
}

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

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

2727
import com.oracle.graal.pointsto.PointsToAnalysis;
28-
import com.oracle.graal.pointsto.api.PointstoOptions;
2928
import com.oracle.graal.pointsto.flow.context.AnalysisContext;
3029
import com.oracle.graal.pointsto.flow.context.BytecodeLocation;
3130
import com.oracle.graal.pointsto.meta.AnalysisType;
@@ -63,17 +62,12 @@ public CloneTypeFlow(PointsToAnalysis bb, CloneTypeFlow original, MethodFlowsGra
6362

6463
@Override
6564
public TypeFlow<BytecodePosition> copy(PointsToAnalysis bb, MethodFlowsGraph methodFlows) {
66-
AnalysisContext enclosingContext = methodFlows.context();
67-
AnalysisContext allocContext = bb.contextPolicy().allocationContext(enclosingContext, PointstoOptions.MaxHeapContextDepth.getValue(bb.getOptions()));
68-
65+
AnalysisContext allocContext = bb.analysisPolicy().allocationContext(bb, methodFlows);
6966
return new CloneTypeFlow(bb, this, methodFlows, allocContext);
7067
}
7168

7269
@Override
7370
public void onObservedUpdate(PointsToAnalysis bb) {
74-
/* Only a clone should be updated */
75-
assert this.isClone() && context != null;
76-
7771
/* The input state has changed, clone its objects. */
7872
TypeState inputState = input.getState();
7973

@@ -92,8 +86,6 @@ public void onObservedUpdate(PointsToAnalysis bb) {
9286

9387
@Override
9488
public void update(PointsToAnalysis bb) {
95-
assert this.isClone();
96-
9789
/* Link the elements of the cloned objects to the elements of the source objects. */
9890
bb.analysisPolicy().linkClonedObjects(bb, input, this, source);
9991

@@ -103,7 +95,6 @@ public void update(PointsToAnalysis bb) {
10395

10496
@Override
10597
public void onObservedSaturated(PointsToAnalysis bb, TypeFlow<?> observed) {
106-
assert this.isClone();
10798
if (!isSaturated()) {
10899
/*
109100
* When the input flow saturates start observing the flow of the declared type, unless

0 commit comments

Comments
 (0)