30
30
import static jdk .graal .compiler .core .GraalCompilerOptions .CompilationFailureAction ;
31
31
import static jdk .graal .compiler .core .GraalCompilerOptions .PrintCompilation ;
32
32
import static jdk .graal .compiler .core .phases .HighTier .Options .Inline ;
33
+ import static jdk .graal .compiler .hotspot .CompilationTask .Options .MethodRecompilationLimit ;
33
34
import static jdk .graal .compiler .java .BytecodeParserOptions .InlineDuringParsing ;
34
35
35
36
import java .io .PrintStream ;
37
+ import java .util .ListIterator ;
36
38
37
39
import org .graalvm .collections .EconomicMap ;
38
40
60
62
import jdk .graal .compiler .nodes .spi .StableProfileProvider .TypeFilter ;
61
63
import jdk .graal .compiler .options .Option ;
62
64
import jdk .graal .compiler .options .OptionKey ;
65
+ import jdk .graal .compiler .options .OptionType ;
63
66
import jdk .graal .compiler .options .OptionValues ;
64
67
import jdk .graal .compiler .options .OptionsParser ;
68
+ import jdk .graal .compiler .phases .BasePhase ;
69
+ import jdk .graal .compiler .phases .common .DeoptimizationGroupingPhase ;
70
+ import jdk .graal .compiler .phases .common .ForceDeoptSpeculationPhase ;
71
+ import jdk .graal .compiler .phases .tiers .MidTierContext ;
72
+ import jdk .graal .compiler .phases .tiers .Suites ;
65
73
import jdk .graal .compiler .printer .GraalDebugHandlersFactory ;
74
+ import jdk .graal .compiler .serviceprovider .GraalServices ;
66
75
import jdk .vm .ci .code .BailoutException ;
67
76
import jdk .vm .ci .code .CodeCacheProvider ;
68
77
import jdk .vm .ci .hotspot .HotSpotCompilationRequest ;
72
81
import jdk .vm .ci .hotspot .HotSpotNmethod ;
73
82
import jdk .vm .ci .hotspot .HotSpotResolvedJavaMethod ;
74
83
import jdk .vm .ci .meta .JavaTypeProfile ;
84
+ import jdk .vm .ci .meta .ProfilingInfo ;
75
85
import jdk .vm .ci .meta .ResolvedJavaMethod ;
76
86
import jdk .vm .ci .runtime .JVMCICompiler ;
77
87
@@ -90,6 +100,10 @@ public static class Options {
90
100
If the value starts with a non-letter character, that
91
101
character is used as the separator between options instead of a space.""" )//
92
102
public static final OptionKey <String > PerMethodOptions = new OptionKey <>(null );
103
+ @ Option (help = "Hard limit on the number of recompilations to avoid deopt loops" , type = OptionType .Debug )//
104
+ public static final OptionKey <Integer > MethodRecompilationLimit = new OptionKey <>(15 );
105
+ @ Option (help = "Try to detect and report the source of deopt loops" , type = OptionType .Debug )//
106
+ public static final OptionKey <Integer > DetectRecompilationLimit = new OptionKey <>(-1 );
93
107
}
94
108
95
109
@ Override
@@ -119,6 +133,10 @@ public void onStuckCompilation(CompilationWatchDog watchDog, Thread watched, Com
119
133
120
134
private final boolean eagerResolving ;
121
135
136
+ protected boolean checkRecompileCycle ;
137
+
138
+ protected final int decompileCount ;
139
+
122
140
/**
123
141
* Filter describing which types in {@link JavaTypeProfile} should be considered for profile
124
142
* writing. This allows programmatically changing which types are saved.
@@ -167,6 +185,10 @@ protected HotSpotCompilationRequestResult handleException(Throwable t) {
167
185
*/
168
186
return HotSpotCompilationRequestResult .failure (bailout .getMessage (), !bailout .isPermanent ());
169
187
}
188
+ if (t instanceof ForceDeoptSpeculationPhase .TooManyDeoptimizationsError ) {
189
+ // Handle this as a permanent bailout
190
+ return HotSpotCompilationRequestResult .failure (t .getMessage (), false );
191
+ }
170
192
171
193
/*
172
194
* Treat random exceptions from the compiler as indicating a problem compiling this
@@ -272,7 +294,23 @@ protected HotSpotCompilationRequestResult performCompilation(DebugContext debug)
272
294
273
295
try (DebugContext .Scope s = debug .scope ("Compiling" , new DebugDumpScope (getIdString (), true ))) {
274
296
graph = compiler .createGraph (method , entryBCI , profileProvider , compilationId , debug .getOptions (), debug );
275
- result = compiler .compile (graph , shouldRetainLocalVariables , shouldUsePreciseUnresolvedDeopts , eagerResolving , compilationId , debug );
297
+ Suites suites = compiler .getSuites (compiler .getGraalRuntime ().getHostProviders (), debug .getOptions ());
298
+ if (checkRecompileCycle && decompileCount < MethodRecompilationLimit .getValue (debug .getOptions ())) {
299
+ /*
300
+ * Disable DeoptimizationGroupingPhase to simplify the creation of the
301
+ * speculations for each deopt.
302
+ */
303
+ ListIterator <BasePhase <? super MidTierContext >> phase = suites .getMidTier ().findPhase (DeoptimizationGroupingPhase .class );
304
+ if (phase != null ) {
305
+ phase .remove ();
306
+ }
307
+ suites .getLowTier ().appendPhase (new ForceDeoptSpeculationPhase <>(decompileCount ));
308
+ }
309
+ result = compiler .compile (graph , shouldRetainLocalVariables , shouldUsePreciseUnresolvedDeopts , eagerResolving , compilationId , debug , suites );
310
+ if (checkRecompileCycle && decompileCount >= MethodRecompilationLimit .getValue (debug .getOptions ())) {
311
+ ProfilingInfo info = profileProvider .getProfilingInfo (method );
312
+ throw new ForceDeoptSpeculationPhase .TooManyDeoptimizationsError ("too many decompiles: " + decompileCount + " " + ForceDeoptSpeculationPhase .getDeoptSummary (info ));
313
+ }
276
314
} catch (Throwable e ) {
277
315
throw debug .handle (e );
278
316
}
@@ -334,6 +372,7 @@ public CompilationTask(HotSpotJVMCIRuntime jvmciRuntime,
334
372
this .shouldUsePreciseUnresolvedDeopts = shouldUsePreciseUnresolvedDeopts ;
335
373
this .eagerResolving = eagerResolving ;
336
374
this .installAsDefault = installAsDefault ;
375
+ this .decompileCount = GraalServices .getDecompileCount (request .getMethod ());
337
376
}
338
377
339
378
public void setTypeFilter (TypeFilter typeFilter ) {
@@ -427,6 +466,10 @@ public int getEntryBCI() {
427
466
return getRequest ().getEntryBCI ();
428
467
}
429
468
469
+ public StableProfileProvider getProfileProvider () {
470
+ return profileProvider ;
471
+ }
472
+
430
473
/**
431
474
* @return the compilation id plus a trailing '%' if the compilation is an OSR to match
432
475
* PrintCompilation style output
0 commit comments