Skip to content

Commit 110d50a

Browse files
committed
introduce Transitive Effect Summary Analysis (TESA)
1 parent d040965 commit 110d50a

File tree

21 files changed

+1207
-39
lines changed

21 files changed

+1207
-39
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/InvokeNode.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,29 +74,33 @@ public final class InvokeNode extends AbstractMemoryCheckpoint implements Invoke
7474
protected int bci;
7575
protected boolean polymorphic;
7676
protected InlineControl inlineControl;
77-
protected final LocationIdentity identity;
77+
/**
78+
* The location killed by the invoke. Typically, it will be {@link LocationIdentity#any()}, but
79+
* an interprocedural analysis can provide more precise location.
80+
*/
81+
protected LocationIdentity killedLocationIdentity;
7882
private boolean isInOOMETry;
7983
private boolean sideEffect;
8084

8185
public InvokeNode(CallTargetNode callTarget, int bci) {
8286
this(callTarget, bci, callTarget.returnStamp().getTrustedStamp());
8387
}
8488

85-
public InvokeNode(CallTargetNode callTarget, int bci, LocationIdentity identity) {
86-
this(callTarget, bci, callTarget.returnStamp().getTrustedStamp(), identity);
89+
public InvokeNode(CallTargetNode callTarget, int bci, LocationIdentity killedLocationIdentity) {
90+
this(callTarget, bci, callTarget.returnStamp().getTrustedStamp(), killedLocationIdentity);
8791
}
8892

8993
public InvokeNode(CallTargetNode callTarget, int bci, Stamp stamp) {
9094
this(callTarget, bci, stamp, LocationIdentity.any());
9195
}
9296

93-
public InvokeNode(CallTargetNode callTarget, int bci, Stamp stamp, LocationIdentity identity) {
97+
public InvokeNode(CallTargetNode callTarget, int bci, Stamp stamp, LocationIdentity killedLocationIdentity) {
9498
super(TYPE, stamp);
9599
this.callTarget = callTarget;
96100
this.bci = bci;
97101
this.polymorphic = false;
98102
this.inlineControl = InlineControl.Normal;
99-
this.identity = identity;
103+
this.killedLocationIdentity = killedLocationIdentity;
100104
this.sideEffect = super.hasSideEffect();
101105
}
102106

@@ -125,6 +129,10 @@ public void setPolymorphic(boolean value) {
125129
this.polymorphic = value;
126130
}
127131

132+
public void setKilledLocationIdentity(LocationIdentity identity) {
133+
this.killedLocationIdentity = identity;
134+
}
135+
128136
@Override
129137
public void setInlineControl(InlineControl control) {
130138
this.inlineControl = control;
@@ -146,7 +154,7 @@ public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
146154

147155
@Override
148156
public LocationIdentity getKilledLocationIdentity() {
149-
return identity;
157+
return killedLocationIdentity;
150158
}
151159

152160
@Override

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/InvokeWithExceptionNode.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434

3535
import java.util.Map;
3636

37+
import org.graalvm.word.LocationIdentity;
38+
3739
import jdk.graal.compiler.core.common.type.Stamp;
3840
import jdk.graal.compiler.graph.IterableNodeType;
3941
import jdk.graal.compiler.graph.Node;
@@ -49,8 +51,6 @@
4951
import jdk.graal.compiler.nodes.spi.SimplifierTool;
5052
import jdk.graal.compiler.nodes.spi.UncheckedInterfaceProvider;
5153
import jdk.graal.compiler.nodes.util.GraphUtil;
52-
import org.graalvm.word.LocationIdentity;
53-
5454
import jdk.vm.ci.code.BytecodeFrame;
5555

5656
// @formatter:off
@@ -70,6 +70,12 @@ public final class InvokeWithExceptionNode extends WithExceptionNode implements
7070
protected boolean polymorphic;
7171
protected InlineControl inlineControl;
7272
private boolean isInOOMETry;
73+
/**
74+
* The location killed by the invoke. Typically, it will be {@link LocationIdentity#any()}, but
75+
* an interprocedural analysis can provide more precise location.
76+
*/
77+
private LocationIdentity killedLocationIdentity = LocationIdentity.any();
78+
private boolean sideEffect = true;
7379

7480
public InvokeWithExceptionNode(CallTargetNode callTarget, AbstractBeginNode exceptionEdge, int bci) {
7581
super(TYPE, callTarget.returnStamp().getTrustedStamp());
@@ -158,12 +164,16 @@ public void setStateAfter(FrameState stateAfter) {
158164

159165
@Override
160166
public boolean hasSideEffect() {
161-
return true;
167+
return sideEffect;
162168
}
163169

164170
@Override
165171
public LocationIdentity getKilledLocationIdentity() {
166-
return LocationIdentity.any();
172+
return killedLocationIdentity;
173+
}
174+
175+
public void setKilledLocationIdentity(LocationIdentity killedLocationIdentity) {
176+
this.killedLocationIdentity = killedLocationIdentity;
167177
}
168178

169179
@Override
@@ -264,4 +274,8 @@ public boolean isInOOMETry() {
264274
public void setInOOMETry(boolean isInOOMETry) {
265275
this.isInOOMETry = isInOOMETry;
266276
}
277+
278+
public void setSideEffect(boolean withSideEffects) {
279+
this.sideEffect = withSideEffects;
280+
}
267281
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/StructuredGraph.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,13 @@ public ParameterNode getParameter(int index) {
861861
return null;
862862
}
863863

864+
/**
865+
* Returns an iterable for looping over all {@link Invoke}s that are associated with
866+
* {@link MethodCallTargetNode}s. Note that since the internal iteration is based on
867+
* {@link MethodCallTargetNode}s, it <b>does not</b> cover other kinds of invokes in the graph.
868+
* If accessing all invokes is necessary for correctness, use a loop over all nodes with
869+
* {@link #getNodes()} and an {@code instanceof} check instead.
870+
*/
864871
public Iterable<Invoke> getInvokes() {
865872
final Iterator<MethodCallTargetNode> callTargets = getNodes(MethodCallTargetNode.TYPE).iterator();
866873
return new Iterable<>() {

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/MemoryEdgeProxy.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@
2424
*/
2525
package jdk.graal.compiler.nodes.spi;
2626

27-
import jdk.graal.compiler.nodes.memory.MemoryKill;
2827
import org.graalvm.word.LocationIdentity;
2928

30-
public interface MemoryEdgeProxy extends Proxy, MemoryKill {
29+
import jdk.graal.compiler.nodes.memory.SingleMemoryKill;
30+
31+
public interface MemoryEdgeProxy extends Proxy, SingleMemoryKill {
3132

3233
LocationIdentity getLocationIdentity();
3334
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ public void cleanupAfterAnalysis() {
257257
@Override
258258
public void printTimerStatistics(PrintWriter out) {
259259
// todo print reachability here
260-
StatisticsPrinter.print(out, "features_time_ms", processFeaturesTimer.getTotalTime());
261-
StatisticsPrinter.print(out, "total_analysis_time_ms", analysisTimer.getTotalTime());
260+
StatisticsPrinter.print(out, "features_time_ms", processFeaturesTimer.getTotalTimeMs());
261+
StatisticsPrinter.print(out, "total_analysis_time_ms", analysisTimer.getTotalTimeMs());
262262

263263
StatisticsPrinter.printLast(out, "total_memory_bytes", analysisTimer.getTotalMemory());
264264
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,10 @@ protected CompletionExecutor.Timing getTiming() {
187187

188188
@Override
189189
public void printTimerStatistics(PrintWriter out) {
190-
StatisticsPrinter.print(out, "typeflow_time_ms", typeFlowTimer.getTotalTime());
191-
StatisticsPrinter.print(out, "verify_time_ms", verifyHeapTimer.getTotalTime());
192-
StatisticsPrinter.print(out, "features_time_ms", processFeaturesTimer.getTotalTime());
193-
StatisticsPrinter.print(out, "total_analysis_time_ms", analysisTimer.getTotalTime());
190+
StatisticsPrinter.print(out, "typeflow_time_ms", typeFlowTimer.getTotalTimeMs());
191+
StatisticsPrinter.print(out, "verify_time_ms", verifyHeapTimer.getTotalTimeMs());
192+
StatisticsPrinter.print(out, "features_time_ms", processFeaturesTimer.getTotalTimeMs());
193+
StatisticsPrinter.print(out, "total_analysis_time_ms", analysisTimer.getTotalTimeMs());
194194

195195
StatisticsPrinter.printLast(out, "total_memory_bytes", analysisTimer.getTotalMemory());
196196
}

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/Timer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ public void stop() {
5454
}
5555

5656
/** Get timer total time in milliseconds. */
57-
public double getTotalTime() {
58-
return totalTime / 1000000d;
57+
public double getTotalTimeMs() {
58+
return totalTime / 1_000_000d;
5959
}
6060

6161
/** Get total VM memory in bytes. */

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/TimerCollection.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,18 @@
2424
*/
2525
package com.oracle.graal.pointsto.util;
2626

27-
import com.oracle.graal.pointsto.reports.StatisticsPrinter;
28-
import com.oracle.svm.util.ImageBuildStatistics;
29-
import jdk.graal.compiler.debug.GraalError;
30-
import org.graalvm.nativeimage.ImageSingletons;
31-
3227
import java.io.PrintWriter;
3328
import java.util.Iterator;
3429
import java.util.Map;
3530
import java.util.concurrent.ConcurrentHashMap;
3631

32+
import org.graalvm.nativeimage.ImageSingletons;
33+
34+
import com.oracle.graal.pointsto.reports.StatisticsPrinter;
35+
import com.oracle.svm.util.ImageBuildStatistics;
36+
37+
import jdk.graal.compiler.debug.GraalError;
38+
3739
public class TimerCollection implements ImageBuildStatistics.TimerCollectionPrinter {
3840

3941
public static TimerCollection singleton() {
@@ -102,7 +104,7 @@ public void printTimerStats(PrintWriter out) {
102104
Iterator<Timer> it = this.timers.values().iterator();
103105
while (it.hasNext()) {
104106
Timer timer = it.next();
105-
StatisticsPrinter.print(out, timer.getName() + "_time", ((int) timer.getTotalTime()));
107+
StatisticsPrinter.print(out, timer.getName() + "_time", ((int) timer.getTotalTimeMs()));
106108
if (it.hasNext()) {
107109
StatisticsPrinter.print(out, timer.getName() + "_memory", timer.getTotalMemory());
108110
} else {

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@
201201
import com.oracle.svm.hosted.analysis.ReachabilityTracePrinter;
202202
import com.oracle.svm.hosted.analysis.SVMAnalysisMetaAccess;
203203
import com.oracle.svm.hosted.analysis.SubstrateUnsupportedFeatures;
204+
import com.oracle.svm.hosted.analysis.tesa.TransitiveEffectSummaryAnalysisEngine;
204205
import com.oracle.svm.hosted.annotation.SubstrateAnnotationExtractor;
205206
import com.oracle.svm.hosted.c.CAnnotationProcessorCache;
206207
import com.oracle.svm.hosted.c.CConstantValueSupportImpl;
@@ -253,6 +254,7 @@
253254
import com.oracle.svm.hosted.phases.SubstrateClassInitializationPlugin;
254255
import com.oracle.svm.hosted.phases.VerifyDeoptLIRFrameStatesPhase;
255256
import com.oracle.svm.hosted.phases.VerifyNoGuardsPhase;
257+
import com.oracle.svm.hosted.pltgot.PLTGOTOptions;
256258
import com.oracle.svm.hosted.reflect.proxy.ProxyRenamingSubstitutionProcessor;
257259
import com.oracle.svm.hosted.snippets.SubstrateGraphBuilderPlugins;
258260
import com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor;
@@ -594,6 +596,15 @@ protected void doRun(Map<Method, CEntryPointData> entryPoints, JavaMainSupport j
594596
new UniverseBuilder(aUniverse, bb.getMetaAccess(), hUniverse, hMetaAccess, HostedConfiguration.instance().createStrengthenGraphs(bb, hUniverse),
595597
bb.getUnsupportedFeatures()).build(debug);
596598

599+
if (TransitiveEffectSummaryAnalysisEngine.enabled()) {
600+
/*
601+
* Fixed-point loops are started after universe building, because the initial
602+
* state for each method is computed after strengthen graphs, which is executed
603+
* in UniverseBuilder.
604+
*/
605+
TransitiveEffectSummaryAnalysisEngine.get().runFixedPointLoops(bb);
606+
}
607+
597608
BuildPhaseProvider.markHostedUniverseBuilt();
598609
ClassInitializationSupport classInitializationSupport = bb.getHostVM().getClassInitializationSupport();
599610
SubstratePlatformConfigurationProvider platformConfig = getPlatformConfig(hMetaAccess);
@@ -825,6 +836,16 @@ protected boolean runPointsToAnalysis(String imageName, OptionValues options, De
825836
HostedImageLayerBuildingSupport.singleton().getWriter().initializeExternalValues();
826837
}
827838
}
839+
if (TransitiveEffectSummaryAnalysisEngine.enabled()) {
840+
/*
841+
* Seal the TESA engine, prevent more analyses from being registered.
842+
* Technically, we could currently allow registrations even during the
843+
* Feature#beforeUniverseBuilding callbacks. But we are intentionally being
844+
* stricter about registrations in case we would like to perform some TESA steps
845+
* already during or immediately after PTA in the future.
846+
*/
847+
TransitiveEffectSummaryAnalysisEngine.get().seal();
848+
}
828849
}
829850

830851
try (ReporterClosable _ = ProgressReporter.singleton().printAnalysis(bb.getUniverse(), nativeLibraries.getLibraries())) {
@@ -881,6 +902,10 @@ protected boolean runPointsToAnalysis(String imageName, OptionValues options, De
881902
bb.getUnsupportedFeatures().report(bb);
882903
bb.checkUserLimitations();
883904

905+
if (TransitiveEffectSummaryAnalysisEngine.enabled()) {
906+
TransitiveEffectSummaryAnalysisEngine.get().saveCallGraph(bb);
907+
}
908+
884909
bb.afterAnalysis();
885910
} catch (UnsupportedFeatureException ufe) {
886911
throw FallbackFeature.reportAsFallback(ufe);
@@ -1056,6 +1081,18 @@ protected void setupNativeImage(OptionValues options, Map<Method, CEntryPointDat
10561081

10571082
bb = createBigBang(debug, options, aUniverse, aMetaAccess, aProviders, annotationSubstitutions);
10581083
aUniverse.setBigBang(bb);
1084+
if (TransitiveEffectSummaryAnalysisEngine.Options.TransitiveEffectSummaryAnalysis.getValue()) {
1085+
/*
1086+
* Tesa only works in ClosedTypeWorld. PLTGOT seems to create memory kills
1087+
* unseen by TESA.
1088+
*/
1089+
if (SubstrateOptions.ClosedTypeWorld.getValue() && !PLTGOTOptions.EnablePLTGOT.getValue()) {
1090+
TransitiveEffectSummaryAnalysisEngine engine = new TransitiveEffectSummaryAnalysisEngine();
1091+
ImageSingletons.add(TransitiveEffectSummaryAnalysisEngine.class, engine);
1092+
/* Register the engine in ImageBuildStatistics for reporting. */
1093+
ImageSingletons.add(ImageBuildStatistics.TransitiveEffectSummaryAnalysisPrinter.class, engine);
1094+
}
1095+
}
10591096
if (imageLayerLoader != null) {
10601097
imageLayerLoader.initNodeClassMap();
10611098
}

0 commit comments

Comments
 (0)