Skip to content

Commit c392e2a

Browse files
committed
[GR-69633] Refactor StrengthenGraphs follow up.
PullRequest: graal/22144
2 parents 7e5943a + 521bb73 commit c392e2a

File tree

8 files changed

+73
-59
lines changed

8 files changed

+73
-59
lines changed

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/HostVM.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import java.util.Optional;
3535
import java.util.concurrent.CopyOnWriteArrayList;
3636
import java.util.function.BiConsumer;
37-
import java.util.function.Function;
37+
import java.util.function.Predicate;
3838

3939
import org.graalvm.nativeimage.hosted.Feature.DuringAnalysisAccess;
4040

@@ -550,8 +550,8 @@ public boolean ignoreInstanceOfTypeDisallowed() {
550550
/**
551551
* Returns the function Strengthen Graphs should use to improve types based on analysis results.
552552
*/
553-
public Function<AnalysisType, ResolvedJavaType> getStrengthenGraphsToTargetFunction(@SuppressWarnings("unused") MultiMethod.MultiMethodKey key) {
554-
return (t) -> t;
553+
public Predicate<AnalysisType> getStrengthenGraphsTypePredicate(@SuppressWarnings("unused") MultiMethod.MultiMethodKey key) {
554+
return (t) -> true;
555555
}
556556

557557
public boolean allowConstantFolding(AnalysisMethod method) {

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/ReachabilitySimplifier.java

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@
2424
*/
2525
package com.oracle.graal.pointsto.results;
2626

27-
import java.util.function.Function;
27+
import java.util.function.Predicate;
2828
import java.util.function.Supplier;
2929

3030
import com.oracle.graal.pointsto.heap.ImageHeapConstant;
3131
import com.oracle.graal.pointsto.meta.AnalysisField;
3232
import com.oracle.graal.pointsto.meta.AnalysisMethod;
3333
import com.oracle.graal.pointsto.meta.AnalysisType;
34+
import com.oracle.graal.pointsto.results.StrengthenGraphs.AnalysisStrengthenGraphsPhase;
3435
import com.oracle.graal.pointsto.util.AnalysisError;
3536

3637
import jdk.graal.compiler.core.common.type.AbstractObjectStamp;
@@ -65,7 +66,6 @@
6566
import jdk.graal.compiler.phases.common.inlining.InliningUtil;
6667
import jdk.graal.compiler.replacements.nodes.MacroInvokable;
6768
import jdk.vm.ci.meta.JavaKind;
68-
import jdk.vm.ci.meta.ResolvedJavaType;
6969

7070
/**
7171
* Simplify graphs based on reachability information tracked by the static analysis.
@@ -76,16 +76,16 @@ class ReachabilitySimplifier implements CustomSimplification {
7676
protected final StructuredGraph graph;
7777

7878
/**
79-
* For runtime compiled methods, we must be careful to ensure new SubstrateTypes are not created
80-
* due to the optimizations performed during the
81-
* {@link StrengthenGraphs.AnalysisStrengthenGraphsPhase}.
79+
* Tests if a SubstrateTypes was already created for the corresponding {@link AnalysisType}. For
80+
* runtime compiled methods, we must be careful to ensure new SubstrateTypes are not created due
81+
* to the optimizations performed during the {@link AnalysisStrengthenGraphsPhase}.
8282
*/
83-
protected final Function<AnalysisType, ResolvedJavaType> toTargetFunction;
83+
protected final Predicate<AnalysisType> typePredicate;
8484

8585
ReachabilitySimplifier(StrengthenGraphs strengthenGraphs, AnalysisMethod method, StructuredGraph graph) {
8686
this.strengthenGraphs = strengthenGraphs;
8787
this.graph = graph;
88-
this.toTargetFunction = strengthenGraphs.bb.getHostVM().getStrengthenGraphsToTargetFunction(method.getMultiMethodKey());
88+
this.typePredicate = strengthenGraphs.bb.getHostVM().getStrengthenGraphsTypePredicate(method.getMultiMethodKey());
8989
}
9090

9191
@Override
@@ -283,18 +283,26 @@ protected String location(Node node) {
283283
return "method " + StrengthenGraphs.getQualifiedName(graph) + ", node " + node;
284284
}
285285

286+
/**
287+
* Tries to improve the stamp based on reachability information. It only handles
288+
* {@link AbstractObjectStamp object stamps} as all primitives types are considered implicitly
289+
* reachable and the analysis (reachability or points-to) doesn't track primitive ranges.
290+
* <p>
291+
* Returns a new {@link Stamp} if the input stamp can be improved, or {@code null} otherwise.
292+
*/
286293
private Stamp strengthenStamp(Stamp s) {
287294
if (!(s instanceof AbstractObjectStamp stamp)) {
295+
/* We can only strengthen object types. */
288296
return null;
289297
}
290298
AnalysisType originalType = (AnalysisType) stamp.type();
291299
if (originalType == null) {
300+
/* The stamp is either empty or a non-exact java.lang.Object; nothing to strengthen. */
292301
return null;
293302
}
294303

295304
/* In open world the type may become reachable later. */
296305
if (strengthenGraphs.isClosedTypeWorld && !originalType.isReachable()) {
297-
/* We must be in dead code. */
298306
if (stamp.nonNull()) {
299307
/* We must be in dead code. */
300308
return StampFactory.empty(JavaKind.Object);
@@ -305,9 +313,8 @@ private Stamp strengthenStamp(Stamp s) {
305313

306314
AnalysisType singleImplementorType = strengthenGraphs.getSingleImplementorType(originalType);
307315
if (singleImplementorType != null && (!stamp.isExactType() || !singleImplementorType.equals(originalType))) {
308-
ResolvedJavaType targetType = toTargetFunction.apply(singleImplementorType);
309-
if (targetType != null) {
310-
TypeReference typeRef = TypeReference.createExactTrusted(targetType);
316+
if (typePredicate.test(singleImplementorType)) {
317+
TypeReference typeRef = TypeReference.createExactTrusted(singleImplementorType);
311318
return StampFactory.object(typeRef, stamp.nonNull());
312319
}
313320
}
@@ -318,29 +325,25 @@ private Stamp strengthenStamp(Stamp s) {
318325
return null;
319326
}
320327

321-
Stamp newStamp;
322328
if (strengthenType == null) {
323329
/* The type and its subtypes are not instantiated. */
324330
if (stamp.nonNull()) {
325331
/* We must be in dead code. */
326-
newStamp = StampFactory.empty(JavaKind.Object);
332+
return StampFactory.empty(JavaKind.Object);
327333
} else {
328-
newStamp = StampFactory.alwaysNull();
334+
return StampFactory.alwaysNull();
329335
}
330-
331336
} else {
332337
if (stamp.isExactType()) {
333338
/* We must be in dead code. */
334-
newStamp = StampFactory.empty(JavaKind.Object);
339+
return StampFactory.empty(JavaKind.Object);
335340
} else {
336-
ResolvedJavaType targetType = toTargetFunction.apply(strengthenType);
337-
if (targetType == null) {
338-
return null;
341+
if (typePredicate.test(strengthenType)) {
342+
TypeReference typeRef = TypeReference.createTrustedWithoutAssumptions(strengthenType);
343+
return StampFactory.object(typeRef, stamp.nonNull());
339344
}
340-
TypeReference typeRef = TypeReference.createTrustedWithoutAssumptions(targetType);
341-
newStamp = StampFactory.object(typeRef, stamp.nonNull());
345+
return null;
342346
}
343347
}
344-
return newStamp;
345348
}
346349
}

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -244,23 +244,26 @@ public final void applyResults(AnalysisMethod method) {
244244

245245
protected abstract void persistStrengthenGraph(AnalysisMethod method);
246246

247-
/*
247+
/**
248248
* Returns a type that can replace the original type in stamps as an exact type. When the
249249
* returned type is the original type itself, the original type has no subtype and can be used
250250
* as an exact type.
251-
*
252-
* Returns null if there is no single implementor type.
251+
* <p>
252+
* Returns {@code null} if there is no optimization potential, i.e., if the original type
253+
* doesn't have a unique implementor type, or we cannot prove that it has a unique implementor
254+
* type due to open-world analysis.
253255
*/
254256
protected abstract AnalysisType getSingleImplementorType(AnalysisType originalType);
255257

256-
/*
258+
/**
257259
* Returns a type that can replace the original type in stamps.
258-
*
259-
* Returns null if the original type has no assignable type that is instantiated, i.e., the code
260-
* using the type is unreachable.
261-
*
260+
* <p>
261+
* Returns {@code null} if the original type has no assignable type that is instantiated, i.e.,
262+
* the code using the type is unreachable.
263+
* <p>
262264
* Returns the original type itself if there is no optimization potential, i.e., if the original
263-
* type itself is instantiated or has more than one instantiated direct subtype.
265+
* type itself is instantiated or has more than one instantiated direct subtype, or we cannot
266+
* prove that it doesn't have any instantiated subtype due to open-world analysis.
264267
*/
265268
protected abstract AnalysisType getStrengthenStampType(AnalysisType originalType);
266269

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/TypeFlowSimplifier.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@
9090
import jdk.vm.ci.meta.JavaMethodProfile;
9191
import jdk.vm.ci.meta.JavaTypeProfile;
9292
import jdk.vm.ci.meta.PrimitiveConstant;
93-
import jdk.vm.ci.meta.ResolvedJavaType;
9493

9594
/**
9695
* Simplify graphs based on reachability information tracked by the static analysis. Additionally,
@@ -640,9 +639,8 @@ private Object strengthenStampFromTypeFlow(ValueNode node, TypeFlow<?> nodeFlow,
640639
assert exactType.equals(strengthenGraphs.getStrengthenStampType(exactType)) : exactType;
641640

642641
if (!oldStamp.isExactType() || !exactType.equals(oldType)) {
643-
ResolvedJavaType targetType = toTargetFunction.apply(exactType);
644-
if (targetType != null) {
645-
TypeReference typeRef = TypeReference.createExactTrusted(targetType);
642+
if (typePredicate.test(exactType)) {
643+
TypeReference typeRef = TypeReference.createExactTrusted(exactType);
646644
return StampFactory.object(typeRef, nonNull);
647645
}
648646
}
@@ -678,9 +676,8 @@ private Object strengthenStampFromTypeFlow(ValueNode node, TypeFlow<?> nodeFlow,
678676
assert typeStateTypes.stream().map(newType::isAssignableFrom).reduce(Boolean::logicalAnd).get() : typeStateTypes;
679677

680678
if (!newType.equals(oldType) && (oldType != null || !newType.isJavaLangObject())) {
681-
ResolvedJavaType targetType = toTargetFunction.apply(newType);
682-
if (targetType != null) {
683-
TypeReference typeRef = TypeReference.createTrustedWithoutAssumptions(targetType);
679+
if (typePredicate.test(newType)) {
680+
TypeReference typeRef = TypeReference.createTrustedWithoutAssumptions(newType);
684681
return StampFactory.object(typeRef, nonNull);
685682
}
686683
}

substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationFeature.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -825,15 +825,15 @@ public InlineBeforeAnalysisPolicy inlineBeforeAnalysisPolicy(MultiMethod.MultiMe
825825
}
826826

827827
@Override
828-
public Function<AnalysisType, ResolvedJavaType> getStrengthenGraphsToTargetFunction(MultiMethod.MultiMethodKey key) {
828+
public Predicate<AnalysisType> getStrengthenGraphsTypePredicate(MultiMethod.MultiMethodKey key) {
829829
if (key == RUNTIME_COMPILED_METHOD) {
830830
/*
831831
* For runtime compiled methods, we must be careful to ensure new SubstrateTypes are
832832
* not created during the AnalysisStrengthenGraphsPhase. If the type does not
833833
* already exist at this point (which is after the analysis phase), then we must
834-
* return null.
834+
* return false.
835835
*/
836-
return (t) -> objectReplacer.typeCreated(t) ? t : null;
836+
return (t) -> objectReplacer.typeCreated(t);
837837
}
838838
return null;
839839
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
import java.util.concurrent.CopyOnWriteArrayList;
4444
import java.util.function.BiPredicate;
4545
import java.util.function.BooleanSupplier;
46-
import java.util.function.Function;
4746
import java.util.function.Predicate;
4847

4948
import org.graalvm.nativeimage.AnnotationAccess;
@@ -1432,14 +1431,14 @@ public boolean ignoreInstanceOfTypeDisallowed() {
14321431
}
14331432

14341433
@Override
1435-
public Function<AnalysisType, ResolvedJavaType> getStrengthenGraphsToTargetFunction(MultiMethod.MultiMethodKey key) {
1434+
public Predicate<AnalysisType> getStrengthenGraphsTypePredicate(MultiMethod.MultiMethodKey key) {
14361435
if (parsingSupport != null) {
1437-
var result = parsingSupport.getStrengthenGraphsToTargetFunction(key);
1436+
var result = parsingSupport.getStrengthenGraphsTypePredicate(key);
14381437
if (result != null) {
14391438
return result;
14401439
}
14411440
}
1442-
return super.getStrengthenGraphsToTargetFunction(key);
1441+
return super.getStrengthenGraphsTypePredicate(key);
14431442
}
14441443

14451444
@Override

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/SVMParsingSupport.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
*/
2525
package com.oracle.svm.hosted.analysis;
2626

27-
import java.util.function.Function;
27+
import java.util.function.Predicate;
2828

2929
import com.oracle.graal.pointsto.BigBang;
3030
import com.oracle.graal.pointsto.PointsToAnalysis;
@@ -39,7 +39,6 @@
3939
import jdk.graal.compiler.debug.DebugContext;
4040
import jdk.graal.compiler.nodes.StructuredGraph;
4141
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
42-
import jdk.vm.ci.meta.ResolvedJavaType;
4342

4443
/**
4544
* {@link com.oracle.graal.pointsto.api.HostVM} methods which may be overwritten by substratevm
@@ -65,5 +64,5 @@ public interface SVMParsingSupport {
6564

6665
InlineBeforeAnalysisPolicy inlineBeforeAnalysisPolicy(MultiMethod.MultiMethodKey multiMethodKey, InlineBeforeAnalysisPolicy defaultPolicy);
6766

68-
Function<AnalysisType, ResolvedJavaType> getStrengthenGraphsToTargetFunction(MultiMethod.MultiMethodKey key);
67+
Predicate<AnalysisType> getStrengthenGraphsTypePredicate(MultiMethod.MultiMethodKey key);
6968
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedType.java

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ public abstract class HostedType extends HostedElement implements SharedType, Wr
6565

6666
boolean loadedFromPriorLayer;
6767
protected int typeID;
68-
protected HostedType uniqueConcreteImplementation;
6968
protected HostedMethod[] allDeclaredMethods;
7069

7170
// region closed-world only fields
@@ -140,13 +139,27 @@ public abstract class HostedType extends HostedElement implements SharedType, Wr
140139
// endregion open-world only fields
141140

142141
/**
143-
* A more precise subtype that can replace this type as the declared type of values. Null if
144-
* this type is never instantiated and does not have any instantiated subtype, i.e., if no value
145-
* of this type can ever exist. Equal to this type if this type is instantiated, i.e, this type
146-
* cannot be strengthened.
147-
*
148-
* For open world the strengthen stamp type is equal to this type itself if the type is not a
149-
* leaf type, i.e., it cannot be extended.
142+
* The unique implementor of this type that can replace it in stamps as an exact type.
143+
* <p>
144+
* A {@code null} value means there is no unique implementor that can replace this type. The
145+
* field is set to this type itself if it has no instantiated subtypes to enable its usage as an
146+
* exact type, e.g., in places where the original stamp was non-exact.
147+
* <p>
148+
* In open-world analysis the field is set to {@code null} for non-leaf types since we have to
149+
* assume that there may be some instantiated subtypes that we haven't seen yet.
150+
*/
151+
protected HostedType uniqueConcreteImplementation;
152+
153+
/**
154+
* A more precise subtype that can replace this type as the declared type of values.
155+
* <p>
156+
* A {@code null} value means that this type is never instantiated and does not have any
157+
* instantiated subtype, i.e., no value of this type can ever exist and the code using this type
158+
* is unreachable. It is set to this type if this type is itself instantiated or has more than
159+
* one instantiated direct subtype, i.e, this type cannot be strengthened.
160+
* <p>
161+
* In open-world analysis the field is set to this type itself for non-leaf types since we have
162+
* to assume that there may be some instantiated subtypes that we haven't seen yet.
150163
*/
151164
protected HostedType strengthenStampType;
152165

0 commit comments

Comments
 (0)