15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24
25 package org.graalvm.compiler.hotspot;
26
27 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Diagnose;
28 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM;
29 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
30 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
31 import static org.graalvm.compiler.core.phases.HighTier.Options.Inline;
32 import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
33
34 import java.io.PrintStream;
35 import java.util.List;
36
37 import jdk.internal.vm.compiler.collections.EconomicMap;
38 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
39 import org.graalvm.compiler.code.CompilationResult;
40 import org.graalvm.compiler.core.CompilationPrinter;
41 import org.graalvm.compiler.core.CompilationWrapper;
42 import org.graalvm.compiler.core.common.CompilationIdentifier;
43 import org.graalvm.compiler.debug.CounterKey;
44 import org.graalvm.compiler.debug.DebugCloseable;
45 import org.graalvm.compiler.debug.DebugContext;
46 import org.graalvm.compiler.debug.DebugDumpScope;
47 import org.graalvm.compiler.debug.GraalError;
48 import org.graalvm.compiler.debug.TimerKey;
49 import org.graalvm.compiler.options.OptionKey;
50 import org.graalvm.compiler.options.OptionValues;
51 import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
52
53 import jdk.vm.ci.code.BailoutException;
54 import jdk.vm.ci.code.CodeCacheProvider;
55 import jdk.vm.ci.hotspot.EventProvider;
56 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
57 import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult;
58 import jdk.vm.ci.hotspot.HotSpotInstalledCode;
59 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
60 import jdk.vm.ci.hotspot.HotSpotNmethod;
61 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
62 import jdk.vm.ci.runtime.JVMCICompiler;
63 import jdk.vm.ci.services.JVMCIServiceLocator;
64
65 public class CompilationTask {
66
67 private static final EventProvider eventProvider;
68
69 static {
70 List<EventProvider> providers = JVMCIServiceLocator.getProviders(EventProvider.class);
71 if (providers.size() > 1) {
72 throw new GraalError("Multiple %s providers found: %s", EventProvider.class.getName(), providers);
73 } else if (providers.isEmpty()) {
74 eventProvider = EventProvider.createEmptyEventProvider();
75 } else {
76 eventProvider = providers.get(0);
77 }
78 }
79
80 private final HotSpotJVMCIRuntime jvmciRuntime;
81
82 private final HotSpotGraalCompiler compiler;
83 private final HotSpotCompilationIdentifier compilationId;
84
85 private HotSpotInstalledCode installedCode;
86
87 /**
88 * Specifies whether the compilation result is installed as the
89 * {@linkplain HotSpotNmethod#isDefault() default} nmethod for the compiled method.
90 */
91 private final boolean installAsDefault;
92
93 private final boolean useProfilingInfo;
94 private final boolean shouldRetainLocalVariables;
95
96 final class HotSpotCompilationWrapper extends CompilationWrapper<HotSpotCompilationRequestResult> {
97 private final EventProvider.CompilationEvent compilationEvent;
98 CompilationResult result;
99
100 HotSpotCompilationWrapper(EventProvider.CompilationEvent compilationEvent) {
101 super(compiler.getGraalRuntime().getOutputDirectory(), compiler.getGraalRuntime().getCompilationProblemsPerAction());
102 this.compilationEvent = compilationEvent;
103 }
104
105 @Override
106 protected DebugContext createRetryDebugContext(OptionValues retryOptions, PrintStream logStream) {
107 SnippetReflectionProvider snippetReflection = compiler.getGraalRuntime().getHostProviders().getSnippetReflection();
108 return DebugContext.create(retryOptions, logStream, new GraalDebugHandlersFactory(snippetReflection));
109 }
110
111 @Override
112 public String toString() {
113 return getMethod().format("%H.%n(%p)");
114 }
115
116 @Override
117 protected HotSpotCompilationRequestResult handleException(Throwable t) {
118 if (t instanceof BailoutException) {
119 BailoutException bailout = (BailoutException) t;
120 /*
121 * Handling of permanent bailouts: Permanent bailouts that can happen for example
122 * due to unsupported unstructured control flow in the bytecodes of a method must
123 * not be retried. Hotspot compile broker will ensure that no recompilation at the
124 * given tier will happen if retry is false.
125 */
126 return HotSpotCompilationRequestResult.failure(bailout.getMessage(), !bailout.isPermanent());
127 }
128 // Log a failure event.
129 EventProvider.CompilerFailureEvent event = eventProvider.newCompilerFailureEvent();
130 if (event.shouldWrite()) {
131 event.setCompileId(getId());
132 event.setMessage(t.getMessage());
133 event.commit();
134 }
135
136 /*
137 * Treat random exceptions from the compiler as indicating a problem compiling this
138 * method. Report the result of toString instead of getMessage to ensure that the
139 * exception type is included in the output in case there's no detail mesage.
140 */
141 return HotSpotCompilationRequestResult.failure(t.toString(), false);
142 }
143
144 @Override
145 protected ExceptionAction lookupAction(OptionValues values, Throwable cause) {
146 if (cause instanceof BailoutException) {
147 BailoutException bailout = (BailoutException) cause;
148 if (bailout.isPermanent()) {
149 // Respect current action if it has been explicitly set.
150 if (!CompilationBailoutAsFailure.hasBeenSet(values)) {
151 // Get more info for permanent bailouts during bootstrap.
152 if (compiler.getGraalRuntime().isBootstrapping()) {
153 return Diagnose;
154 }
164 if (!CompilationFailureAction.hasBeenSet(values)) {
165 // Automatically exit on failure during bootstrap.
166 if (compiler.getGraalRuntime().isBootstrapping()) {
167 return ExitVM;
168 }
169 }
170 return super.lookupAction(values, cause);
171 }
172
173 @SuppressWarnings("try")
174 @Override
175 protected HotSpotCompilationRequestResult performCompilation(DebugContext debug) {
176 HotSpotResolvedJavaMethod method = getMethod();
177 int entryBCI = getEntryBCI();
178 final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
179 CompilationStatistics stats = CompilationStatistics.create(debug.getOptions(), method, isOSR);
180
181 final CompilationPrinter printer = CompilationPrinter.begin(debug.getOptions(), compilationId, method, entryBCI);
182
183 try (DebugContext.Scope s = debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) {
184 // Begin the compilation event.
185 compilationEvent.begin();
186 result = compiler.compile(method, entryBCI, useProfilingInfo, shouldRetainLocalVariables, compilationId, debug);
187 } catch (Throwable e) {
188 throw debug.handle(e);
189 } finally {
190 // End the compilation event.
191 compilationEvent.end();
192 }
193
194 if (result != null) {
195 try (DebugCloseable b = CodeInstallationTime.start(debug)) {
196 installMethod(debug, result);
197 }
198 // Installation is included in compilation time and memory usage reported by printer
199 printer.finish(result);
200 }
201 stats.finish(method, installedCode);
202 if (result != null) {
203 return HotSpotCompilationRequestResult.success(result.getBytecodeSize() - method.getCodeSize());
204 }
205 return null;
206 }
207
208 }
209
210 public CompilationTask(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault) {
211 this(jvmciRuntime, compiler, request, useProfilingInfo, false, installAsDefault);
305 * Time spent in code installation.
306 */
307 public static final TimerKey CodeInstallationTime = DebugContext.timer("CodeInstallation");
308
309 public HotSpotCompilationRequestResult runCompilation(OptionValues initialOptions) {
310 OptionValues options = filterOptions(initialOptions);
311 SnippetReflectionProvider snippetReflection = compiler.getGraalRuntime().getHostProviders().getSnippetReflection();
312 try (DebugContext debug = DebugContext.create(options, new GraalDebugHandlersFactory(snippetReflection))) {
313 return runCompilation(debug);
314 }
315 }
316
317 @SuppressWarnings("try")
318 public HotSpotCompilationRequestResult runCompilation(DebugContext debug) {
319 HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime();
320 GraalHotSpotVMConfig config = graalRuntime.getVMConfig();
321 int entryBCI = getEntryBCI();
322 boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
323 HotSpotResolvedJavaMethod method = getMethod();
324
325 // Log a compilation event.
326 EventProvider.CompilationEvent compilationEvent = eventProvider.newCompilationEvent();
327
328 if (installAsDefault || isOSR) {
329 // If there is already compiled code for this method on our level we simply return.
330 // JVMCI compiles are always at the highest compile level, even in non-tiered mode so we
331 // only need to check for that value.
332 if (method.hasCodeAtLevel(entryBCI, config.compilationLevelFullOptimization)) {
333 return HotSpotCompilationRequestResult.failure("Already compiled", false);
334 }
335 if (HotSpotGraalCompilerFactory.shouldExclude(method)) {
336 return HotSpotCompilationRequestResult.failure("GraalCompileOnly excluded", false);
337 }
338 }
339
340 HotSpotCompilationWrapper compilation = new HotSpotCompilationWrapper(compilationEvent);
341 try (DebugCloseable a = CompilationTime.start(debug)) {
342 return compilation.run(debug);
343 } finally {
344 try {
345 int compiledBytecodes = 0;
346 int codeSize = 0;
347
348 if (compilation.result != null) {
349 compiledBytecodes = compilation.result.getBytecodeSize();
350 CompiledBytecodes.add(debug, compiledBytecodes);
351 if (installedCode != null) {
352 codeSize = installedCode.getSize();
353 CompiledAndInstalledBytecodes.add(debug, compiledBytecodes);
354 InstalledCodeSize.add(debug, codeSize);
355 }
356 }
357
358 // Log a compilation event.
359 if (compilationEvent.shouldWrite()) {
360 compilationEvent.setMethod(method.format("%H.%n(%p)"));
361 compilationEvent.setCompileId(getId());
362 compilationEvent.setCompileLevel(config.compilationLevelFullOptimization);
363 compilationEvent.setSucceeded(compilation.result != null && installedCode != null);
364 compilationEvent.setIsOsr(isOSR);
365 compilationEvent.setCodeSize(codeSize);
366 compilationEvent.setInlinedBytes(compiledBytecodes);
367 compilationEvent.commit();
368 }
369 } catch (Throwable t) {
370 return compilation.handleException(t);
371 }
372 }
373 }
374
375 @SuppressWarnings("try")
376 private void installMethod(DebugContext debug, final CompilationResult compResult) {
377 final CodeCacheProvider codeCache = jvmciRuntime.getHostJVMCIBackend().getCodeCache();
378 HotSpotBackend backend = compiler.getGraalRuntime().getHostBackend();
379 installedCode = null;
380 Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult};
381 try (DebugContext.Scope s = debug.scope("CodeInstall", context)) {
382 HotSpotCompilationRequest request = getRequest();
383 installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug,
384 request.getMethod(),
385 request,
386 compResult,
387 null,
|
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24
25 package org.graalvm.compiler.hotspot;
26
27 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Diagnose;
28 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM;
29 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
30 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
31 import static org.graalvm.compiler.core.phases.HighTier.Options.Inline;
32 import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
33
34 import java.io.PrintStream;
35
36 import jdk.internal.vm.compiler.collections.EconomicMap;
37 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
38 import org.graalvm.compiler.code.CompilationResult;
39 import org.graalvm.compiler.core.CompilationPrinter;
40 import org.graalvm.compiler.core.CompilationWrapper;
41 import org.graalvm.compiler.core.common.CompilationIdentifier;
42 import org.graalvm.compiler.debug.CounterKey;
43 import org.graalvm.compiler.debug.DebugCloseable;
44 import org.graalvm.compiler.debug.DebugContext;
45 import org.graalvm.compiler.debug.DebugDumpScope;
46 import org.graalvm.compiler.debug.TimerKey;
47 import org.graalvm.compiler.options.OptionKey;
48 import org.graalvm.compiler.options.OptionValues;
49 import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
50
51 import jdk.vm.ci.code.BailoutException;
52 import jdk.vm.ci.code.CodeCacheProvider;
53 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
54 import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult;
55 import jdk.vm.ci.hotspot.HotSpotInstalledCode;
56 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
57 import jdk.vm.ci.hotspot.HotSpotNmethod;
58 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
59 import jdk.vm.ci.runtime.JVMCICompiler;
60
61 public class CompilationTask {
62
63 private final HotSpotJVMCIRuntime jvmciRuntime;
64
65 private final HotSpotGraalCompiler compiler;
66 private final HotSpotCompilationIdentifier compilationId;
67
68 private HotSpotInstalledCode installedCode;
69
70 /**
71 * Specifies whether the compilation result is installed as the
72 * {@linkplain HotSpotNmethod#isDefault() default} nmethod for the compiled method.
73 */
74 private final boolean installAsDefault;
75
76 private final boolean useProfilingInfo;
77 private final boolean shouldRetainLocalVariables;
78
79 final class HotSpotCompilationWrapper extends CompilationWrapper<HotSpotCompilationRequestResult> {
80 CompilationResult result;
81
82 HotSpotCompilationWrapper() {
83 super(compiler.getGraalRuntime().getOutputDirectory(), compiler.getGraalRuntime().getCompilationProblemsPerAction());
84 }
85
86 @Override
87 protected DebugContext createRetryDebugContext(OptionValues retryOptions, PrintStream logStream) {
88 SnippetReflectionProvider snippetReflection = compiler.getGraalRuntime().getHostProviders().getSnippetReflection();
89 return DebugContext.create(retryOptions, logStream, new GraalDebugHandlersFactory(snippetReflection));
90 }
91
92 @Override
93 public String toString() {
94 return getMethod().format("%H.%n(%p)");
95 }
96
97 @Override
98 protected HotSpotCompilationRequestResult handleException(Throwable t) {
99 if (t instanceof BailoutException) {
100 BailoutException bailout = (BailoutException) t;
101 /*
102 * Handling of permanent bailouts: Permanent bailouts that can happen for example
103 * due to unsupported unstructured control flow in the bytecodes of a method must
104 * not be retried. Hotspot compile broker will ensure that no recompilation at the
105 * given tier will happen if retry is false.
106 */
107 return HotSpotCompilationRequestResult.failure(bailout.getMessage(), !bailout.isPermanent());
108 }
109
110 /*
111 * Treat random exceptions from the compiler as indicating a problem compiling this
112 * method. Report the result of toString instead of getMessage to ensure that the
113 * exception type is included in the output in case there's no detail mesage.
114 */
115 return HotSpotCompilationRequestResult.failure(t.toString(), false);
116 }
117
118 @Override
119 protected ExceptionAction lookupAction(OptionValues values, Throwable cause) {
120 if (cause instanceof BailoutException) {
121 BailoutException bailout = (BailoutException) cause;
122 if (bailout.isPermanent()) {
123 // Respect current action if it has been explicitly set.
124 if (!CompilationBailoutAsFailure.hasBeenSet(values)) {
125 // Get more info for permanent bailouts during bootstrap.
126 if (compiler.getGraalRuntime().isBootstrapping()) {
127 return Diagnose;
128 }
138 if (!CompilationFailureAction.hasBeenSet(values)) {
139 // Automatically exit on failure during bootstrap.
140 if (compiler.getGraalRuntime().isBootstrapping()) {
141 return ExitVM;
142 }
143 }
144 return super.lookupAction(values, cause);
145 }
146
147 @SuppressWarnings("try")
148 @Override
149 protected HotSpotCompilationRequestResult performCompilation(DebugContext debug) {
150 HotSpotResolvedJavaMethod method = getMethod();
151 int entryBCI = getEntryBCI();
152 final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
153 CompilationStatistics stats = CompilationStatistics.create(debug.getOptions(), method, isOSR);
154
155 final CompilationPrinter printer = CompilationPrinter.begin(debug.getOptions(), compilationId, method, entryBCI);
156
157 try (DebugContext.Scope s = debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) {
158 result = compiler.compile(method, entryBCI, useProfilingInfo, shouldRetainLocalVariables, compilationId, debug);
159 } catch (Throwable e) {
160 throw debug.handle(e);
161 }
162
163 if (result != null) {
164 try (DebugCloseable b = CodeInstallationTime.start(debug)) {
165 installMethod(debug, result);
166 }
167 // Installation is included in compilation time and memory usage reported by printer
168 printer.finish(result);
169 }
170 stats.finish(method, installedCode);
171 if (result != null) {
172 return HotSpotCompilationRequestResult.success(result.getBytecodeSize() - method.getCodeSize());
173 }
174 return null;
175 }
176
177 }
178
179 public CompilationTask(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault) {
180 this(jvmciRuntime, compiler, request, useProfilingInfo, false, installAsDefault);
274 * Time spent in code installation.
275 */
276 public static final TimerKey CodeInstallationTime = DebugContext.timer("CodeInstallation");
277
278 public HotSpotCompilationRequestResult runCompilation(OptionValues initialOptions) {
279 OptionValues options = filterOptions(initialOptions);
280 SnippetReflectionProvider snippetReflection = compiler.getGraalRuntime().getHostProviders().getSnippetReflection();
281 try (DebugContext debug = DebugContext.create(options, new GraalDebugHandlersFactory(snippetReflection))) {
282 return runCompilation(debug);
283 }
284 }
285
286 @SuppressWarnings("try")
287 public HotSpotCompilationRequestResult runCompilation(DebugContext debug) {
288 HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime();
289 GraalHotSpotVMConfig config = graalRuntime.getVMConfig();
290 int entryBCI = getEntryBCI();
291 boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
292 HotSpotResolvedJavaMethod method = getMethod();
293
294 if (installAsDefault || isOSR) {
295 // If there is already compiled code for this method on our level we simply return.
296 // JVMCI compiles are always at the highest compile level, even in non-tiered mode so we
297 // only need to check for that value.
298 if (method.hasCodeAtLevel(entryBCI, config.compilationLevelFullOptimization)) {
299 return HotSpotCompilationRequestResult.failure("Already compiled", false);
300 }
301 if (HotSpotGraalCompilerFactory.shouldExclude(method)) {
302 return HotSpotCompilationRequestResult.failure("GraalCompileOnly excluded", false);
303 }
304 }
305
306 HotSpotCompilationWrapper compilation = new HotSpotCompilationWrapper();
307 try (DebugCloseable a = CompilationTime.start(debug)) {
308 return compilation.run(debug);
309 } finally {
310 try {
311 int compiledBytecodes = 0;
312 int codeSize = 0;
313
314 if (compilation.result != null) {
315 compiledBytecodes = compilation.result.getBytecodeSize();
316 CompiledBytecodes.add(debug, compiledBytecodes);
317 if (installedCode != null) {
318 codeSize = installedCode.getSize();
319 CompiledAndInstalledBytecodes.add(debug, compiledBytecodes);
320 InstalledCodeSize.add(debug, codeSize);
321 }
322 }
323 } catch (Throwable t) {
324 return compilation.handleException(t);
325 }
326 }
327 }
328
329 @SuppressWarnings("try")
330 private void installMethod(DebugContext debug, final CompilationResult compResult) {
331 final CodeCacheProvider codeCache = jvmciRuntime.getHostJVMCIBackend().getCodeCache();
332 HotSpotBackend backend = compiler.getGraalRuntime().getHostBackend();
333 installedCode = null;
334 Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult};
335 try (DebugContext.Scope s = debug.scope("CodeInstall", context)) {
336 HotSpotCompilationRequest request = getRequest();
337 installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug,
338 request.getMethod(),
339 request,
340 compResult,
341 null,
|