Skip to content

Commit 47cf9d0

Browse files
committed
Deopt cycle detection automatically includes node source positions.
1 parent 4372d25 commit 47cf9d0

File tree

5 files changed

+52
-35
lines changed

5 files changed

+52
-35
lines changed

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/truffle/test/SimplePartialEvaluationTest.java

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,25 @@
2424
*/
2525
package jdk.graal.compiler.truffle.test;
2626

27+
import org.graalvm.polyglot.Context;
28+
import org.junit.Assert;
29+
import org.junit.Before;
30+
import org.junit.Test;
31+
2732
import com.oracle.truffle.api.CompilerAsserts;
33+
import com.oracle.truffle.api.frame.FrameDescriptor;
34+
import com.oracle.truffle.api.frame.FrameSlotKind;
35+
import com.oracle.truffle.api.impl.FrameWithoutBoxing;
36+
import com.oracle.truffle.api.nodes.RootNode;
37+
import com.oracle.truffle.runtime.OptimizedCallTarget;
38+
39+
import jdk.graal.compiler.core.common.GraalBailoutException;
40+
import jdk.graal.compiler.core.common.GraalOptions;
41+
import jdk.graal.compiler.core.common.PermanentBailoutException;
42+
import jdk.graal.compiler.debug.TTY;
43+
import jdk.graal.compiler.nodes.StructuredGraph;
44+
import jdk.graal.compiler.options.OptionValues;
45+
import jdk.graal.compiler.replacements.PEGraphDecoder;
2846
import jdk.graal.compiler.truffle.test.nodes.AbstractTestNode;
2947
import jdk.graal.compiler.truffle.test.nodes.AddTestNode;
3048
import jdk.graal.compiler.truffle.test.nodes.BlockTestNode;
@@ -53,24 +71,6 @@
5371
import jdk.graal.compiler.truffle.test.nodes.explosion.NestedExplodedLoopTestNode;
5472
import jdk.graal.compiler.truffle.test.nodes.explosion.TwoMergesExplodedLoopTestNode;
5573
import jdk.graal.compiler.truffle.test.nodes.explosion.UnrollingTestNode;
56-
import jdk.graal.compiler.core.common.GraalBailoutException;
57-
import jdk.graal.compiler.core.common.GraalOptions;
58-
import jdk.graal.compiler.core.common.PermanentBailoutException;
59-
import jdk.graal.compiler.debug.TTY;
60-
import jdk.graal.compiler.nodes.StructuredGraph;
61-
import jdk.graal.compiler.options.OptionValues;
62-
import jdk.graal.compiler.replacements.PEGraphDecoder;
63-
import org.graalvm.polyglot.Context;
64-
import org.junit.Assert;
65-
import org.junit.Before;
66-
import org.junit.Test;
67-
68-
import com.oracle.truffle.api.frame.FrameDescriptor;
69-
import com.oracle.truffle.api.frame.FrameSlotKind;
70-
import com.oracle.truffle.api.impl.FrameWithoutBoxing;
71-
import com.oracle.truffle.api.nodes.RootNode;
72-
import com.oracle.truffle.runtime.OptimizedCallTarget;
73-
7474
import jdk.vm.ci.code.BailoutException;
7575

7676
public class SimplePartialEvaluationTest extends PartialEvaluationTest {

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/PartialEvaluator.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public abstract class PartialEvaluator {
8787
// Configs
8888
protected final TruffleCompilerConfiguration config;
8989
// TODO GR-37097 Move to TruffleCompilerImpl
90-
volatile GraphBuilderConfiguration graphBuilderConfigForParsing;
90+
private volatile GraphBuilderConfiguration graphBuilderConfigForParsing;
9191
// Plugins
9292
private final GraphBuilderConfiguration graphBuilderConfigPrototype;
9393
private final InvocationPlugins firstTierDecodingPlugins;
@@ -388,7 +388,7 @@ public LoopExplosionKind loopExplosionKind(ResolvedJavaMethod method) {
388388
protected PEGraphDecoder createGraphDecoder(TruffleTierContext context, InvocationPlugins invocationPlugins, InlineInvokePlugin[] inlineInvokePlugins, ParameterPlugin parameterPlugin,
389389
NodePlugin[] nodePluginList, SourceLanguagePositionProvider sourceLanguagePositionProvider, EconomicMap<ResolvedJavaMethod, EncodedGraph> graphCache,
390390
Supplier<AutoCloseable> createCachedGraphScope) {
391-
final GraphBuilderConfiguration newConfig = graphBuilderConfigForParsing.copy();
391+
final GraphBuilderConfiguration newConfig = getGraphBuilderConfigurationCopy(context.forceNodeSourcePositions);
392392
InvocationPlugins parsingInvocationPlugins = newConfig.getPlugins().getInvocationPlugins();
393393

394394
Plugins plugins = newConfig.getPlugins();
@@ -412,6 +412,11 @@ protected PEGraphDecoder createGraphDecoder(TruffleTierContext context, Invocati
412412
allowAssumptionsDuringParsing, false, true);
413413
}
414414

415+
private GraphBuilderConfiguration getGraphBuilderConfigurationCopy(boolean forceNodeSourcePositions) {
416+
GraphBuilderConfiguration copy = getGraphBuilderConfigForParsing().copy();
417+
return copy.withNodeSourcePosition(copy.trackNodeSourcePosition() || forceNodeSourcePositions);
418+
}
419+
415420
protected abstract GraphBuilderPhase.Instance createGraphBuilderPhaseInstance(CoreProviders providers, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts);
416421

417422
@SuppressWarnings("try")

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/TruffleTierContext.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,16 @@ public final class TruffleTierContext extends HighTierContext {
6161

6262
public final StructuredGraph graph;
6363
public final PerformanceInformationHandler handler;
64+
public final boolean forceNodeSourcePositions;
6465

6566
private TruffleTierContext(PartialEvaluator partialEvaluator,
6667
OptionValues compilerOptions,
6768
DebugContext debug,
6869
TruffleCompilable compilable,
6970
CompilationIdentifier compilationId, SpeculationLog log,
7071
TruffleCompilationTask task, PerformanceInformationHandler handler,
71-
ResolvedJavaMethod initialMethod) {
72+
ResolvedJavaMethod initialMethod,
73+
boolean forceNodeSourcePositions) {
7274
super(partialEvaluator.getProviders(), new PhaseSuite<>(), OptimisticOptimizations.NONE);
7375
Objects.requireNonNull(debug);
7476
Objects.requireNonNull(compilable);
@@ -83,7 +85,8 @@ private TruffleTierContext(PartialEvaluator partialEvaluator,
8385
this.log = log;
8486
this.task = task;
8587
this.handler = handler;
86-
this.graph = createInitialGraph(initialMethod);
88+
this.forceNodeSourcePositions = forceNodeSourcePositions;
89+
this.graph = createInitialGraph(initialMethod, forceNodeSourcePositions);
8790
}
8891

8992
private TruffleTierContext(TruffleTierContext parent,
@@ -97,7 +100,8 @@ private TruffleTierContext(TruffleTierContext parent,
97100
parent.log,
98101
parent.task,
99102
parent.handler,
100-
initialMethod);
103+
initialMethod,
104+
parent.forceNodeSourcePositions);
101105
}
102106

103107
public static TruffleTierContext createInitialContext(PartialEvaluator partialEvaluator,
@@ -117,7 +121,14 @@ public static TruffleTierContext createInitialContext(PartialEvaluator partialEv
117121
throw new RetryableBailoutException("Compilable not ready for compilation.");
118122
}
119123
ResolvedJavaMethod method = partialEvaluator.rootForCallTarget(compilable);
120-
TruffleTierContext context = new TruffleTierContext(partialEvaluator, compilerOptions, debug, compilable, compilationId, log, task, handler, method);
124+
int deoptCycleDetectionThreshold = TruffleCompilerOptions.DeoptCycleDetectionThreshold.getValue(compilerOptions);
125+
boolean forceNodeSourcePositions;
126+
if (deoptCycleDetectionThreshold >= 0 && compilable.getSuccessfulCompilationCount() >= deoptCycleDetectionThreshold) {
127+
forceNodeSourcePositions = true;
128+
} else {
129+
forceNodeSourcePositions = false;
130+
}
131+
TruffleTierContext context = new TruffleTierContext(partialEvaluator, compilerOptions, debug, compilable, compilationId, log, task, handler, method, forceNodeSourcePositions);
121132
context.recordStabilityAssumptions();
122133
return context;
123134
}
@@ -147,14 +158,14 @@ public TruffleTierContext createFinalizationContext(TruffleCompilable inlinedCom
147158
return new TruffleTierContext(this, inlinedCompilable, partialEvaluator.getCallDirect());
148159
}
149160

150-
private StructuredGraph createInitialGraph(ResolvedJavaMethod method) {
161+
private StructuredGraph createInitialGraph(ResolvedJavaMethod method, boolean forceSourcePositions) {
151162
// @formatter:off
152163
StructuredGraph.Builder builder = new StructuredGraph.Builder(this.debug.getOptions(), this.debug, StructuredGraph.AllowAssumptions.YES).
153164
name(this.compilable.getName()).
154165
method(method).
155166
speculationLog(this.log).
156167
compilationId(this.compilationId).
157-
trackNodeSourcePosition(partialEvaluator.graphBuilderConfigForParsing.trackNodeSourcePosition()).
168+
trackNodeSourcePosition(forceSourcePositions || partialEvaluator.getGraphBuilderConfigForParsing().trackNodeSourcePosition()).
158169
cancellable(new CancellableTask(this.task));
159170
// @formatter:on
160171
return partialEvaluator.customizeStructuredGraphBuilder(builder).build();

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/phases/TruffleForceDeoptSpeculationPhase.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
import com.oracle.truffle.compiler.TruffleCompilable;
2828

29-
import jdk.graal.compiler.core.common.GraalOptions;
3029
import jdk.graal.compiler.core.common.spi.ForeignCallDescriptor;
3130
import jdk.graal.compiler.debug.GraalError;
3231
import jdk.graal.compiler.nodes.StructuredGraph;
@@ -59,13 +58,13 @@ protected int getMaximumDeoptCount(StructuredGraph graph) {
5958
@Override
6059
protected GraalError reportTooManySpeculationFailures(ValueNode deopt) {
6160
StackTraceElement[] elements = GraphUtil.approxSourceStackTraceElement(deopt);
62-
String additionalMessage = "";
63-
if (elements.length == 0 && !TruffleCompilerOptions.NodeSourcePositions.getValue(deopt.graph().getOptions()) &&
64-
!GraalOptions.TrackNodeSourcePosition.getValue(deopt.graph().getOptions())) {
65-
additionalMessage = " Please set the option 'compiler.NodeSourcePositions' to 'true' to get the stacktrace for the location of the deopt.";
66-
}
61+
String additionalMessage = elements.length != 0 ? ""
62+
: " The node source position of the deoptimization is not available. " +
63+
"In a native image, this usually means the image was not built with -H:+IncludeNodeSourcePositions, " +
64+
"otherwise the missing source position typically indicates a compiler bug. Please file an issue.";
6765
throw GraphUtil.createBailoutException(
68-
"Deopt taken too many times: " + deopt + ". This could indicate a deopt cycle, which typically hints at a bug in the language implementation or Truffle." + additionalMessage,
66+
"Deopt taken too many times. Deopt Node: " + deopt + ". This could indicate a deopt cycle, which typically hints at a bug in the language implementation or Truffle." +
67+
additionalMessage,
6968
null, elements);
7069
}
7170
}

truffle/docs/Optimizing.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,9 @@ and then clicking the `Search in following phases` button.
653653
Since the version 25, Truffle has an automatic deoptimization cycle detection feature. This feature is available and enabled by default when running optimized on JDK 25 and later.
654654
Whenever a deoptimization cycle is detected, the compilation fails with a permanent bailout that contains the Java stacktrace of the location, if available.
655655
656-
Compilation failures are not printed by default. One way of printing compilation failures is to set the option `engine.CompilationFailureAction` to `Print`. To also print an approximated stack trace of the deoptimization location, `compiler.NodeSourcePositions` has to be enabled.
656+
Compilation failures are not printed by default. One way of printing compilation failures is to set the option `engine.CompilationFailureAction` to `Print`. This also prints an approximated stack trace of the deoptimization location.
657+
658+
> Note: To get the approximated stack trace of the deoptimization location in a native image, the image has to be built with `-H:+IncludeNodeSourcePositions`.
657659
658660
Deoptimization cycle detection can be completely disabled by setting `compiler.DeoptCycleDetectionThreshold` to `-1`.
659661
@@ -697,7 +699,7 @@ In general, when no new code to compile is introduced, Truffle compilations shou
697699
`InvalidArgumentProfilingNode` contains a bug which causes a deoptimization cycle. When the root node is executed repeatedly and the argument keeps changing, the number of deoptimizations/recompilations is unlimited.
698700
The following command executes the program with the default deoptimization cycle detection and a deopt stacktrace printing for any detected repeated deoptimization.
699701
```commandline
700-
java -Dpolyglot.engine.AllowExperimentalOptions=true -Dpolyglot.compiler.NodeSourcePositions=true -Dpolyglot.engine.CompilationFailureAction=Print DeoptCycleDetectionTest
702+
java -Dpolyglot.engine.CompilationFailureAction=Print DeoptCycleDetectionTest
701703
```
702704
The expected output is
703705
```

0 commit comments

Comments
 (0)