Skip to content

Commit a7ba1e3

Browse files
committed
[GR-68545] Ignore deopt nodes with deopt action "None" for deopt cycle detection.
PullRequest: graal/21783
2 parents a4fba82 + 5cf6dbd commit a7ba1e3

File tree

2 files changed

+49
-5
lines changed

2 files changed

+49
-5
lines changed

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,48 @@ public Object execute(VirtualFrame frame) {
107107
}, "alwaysDeopt", CallTarget::call, 1);
108108
}
109109

110+
@Test
111+
public void testAlwaysDeoptNoInvalidate() {
112+
AssertionError expectedError = Assert.assertThrows(AssertionError.class, () -> assertDeoptLoop(new BaseRootNode() {
113+
@CompilerDirectives.TruffleBoundary
114+
static void boundaryMethod() {
115+
116+
}
117+
118+
@Override
119+
public Object execute(VirtualFrame frame) {
120+
int arg = (int) frame.getArguments()[0];
121+
int threshold = TruffleCompilerOptions.DeoptCycleDetectionThreshold.getDefaultValue();
122+
if (arg < threshold) {
123+
CompilerDirectives.transferToInterpreterAndInvalidate();
124+
}
125+
// call boundary method to prevent compiler from moving the following deoptimization
126+
// up
127+
boundaryMethod();
128+
CompilerDirectives.transferToInterpreter();
129+
return null;
130+
}
131+
}, "alwaysDeoptNoInvalidate", new Consumer<CallTarget>() {
132+
int i;
133+
134+
@Override
135+
public void accept(CallTarget callTarget) {
136+
callTarget.call(i++);
137+
if (i == TruffleCompilerOptions.DeoptCycleDetectionThreshold.getDefaultValue() + 1) {
138+
/*
139+
* Invalidate the target that was just deoptimized (but not invalidated) by
140+
* transferToInterpreter. The exact same compilation is then repeated in the
141+
* next iteration, but because deoptimize nodes with deoptimization action
142+
* "None" (like the one used for transferToInterpreter) don't trigger deopt loop
143+
* detection, no deopt loop should be detected.
144+
*/
145+
((OptimizedCallTarget) callTarget).invalidate("Force one more recompile");
146+
}
147+
}
148+
}, 1));
149+
Assert.assertEquals("No deopt loop detected after " + MAX_EXECUTIONS + " executions", expectedError.getMessage());
150+
}
151+
110152
@Test
111153
public void testLocalDeopt() {
112154
assertDeoptLoop(new BaseRootNode() {

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/ForceDeoptSpeculationPhase.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ protected void run(StructuredGraph graph, CoreProviders context) {
8787
if (node instanceof DynamicDeoptimizeNode) {
8888
throw new GraalError("%s must be disabled to use this phase", DynamicDeoptimizeNode.class.getSimpleName());
8989
}
90-
if (node instanceof DeoptimizeNode deopt) {
90+
if (node instanceof DeoptimizeNode deopt && deopt.getAction() != DeoptimizationAction.None) {
9191
if (deopt.getSpeculation().equals(NO_SPECULATION)) {
9292
SpeculationLog.Speculation speculation = createSpeculation(graph, signature, deopt);
9393
deopt.setSpeculation(speculation);
@@ -97,12 +97,14 @@ protected void run(StructuredGraph graph, CoreProviders context) {
9797
JavaConstant spec = implicitNullCheck.getDeoptSpeculation();
9898
SpeculationLog.Speculation speculation = spec != null ? context.getMetaAccess().decodeSpeculation(spec, speculationLog) : NO_SPECULATION;
9999
if (speculation.equals(NO_SPECULATION)) {
100-
spec = context.getMetaAccess().encodeSpeculation(createSpeculation(graph, signature, implicitNullCheck));
101100
JavaConstant actionAndReason = implicitNullCheck.getDeoptReasonAndAction();
102-
if (actionAndReason == null) {
103-
actionAndReason = context.getMetaAccess().encodeDeoptActionAndReason(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NullCheckException, 0);
101+
if (actionAndReason == null || context.getMetaAccess().decodeDeoptAction(actionAndReason) != DeoptimizationAction.None) {
102+
spec = context.getMetaAccess().encodeSpeculation(createSpeculation(graph, signature, implicitNullCheck));
103+
if (actionAndReason == null) {
104+
actionAndReason = context.getMetaAccess().encodeDeoptActionAndReason(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NullCheckException, 0);
105+
}
106+
implicitNullCheck.setImplicitDeoptimization(actionAndReason, spec);
104107
}
105-
implicitNullCheck.setImplicitDeoptimization(actionAndReason, spec);
106108
}
107109
}
108110
}

0 commit comments

Comments
 (0)