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 package org.graalvm.compiler.hotspot; 24 25 import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnBailout; 26 import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException; 27 import static org.graalvm.compiler.core.GraalCompilerOptions.PrintAfterCompilation; 28 import static org.graalvm.compiler.core.GraalCompilerOptions.PrintBailout; 29 import static org.graalvm.compiler.core.GraalCompilerOptions.PrintCompilation; 30 import static org.graalvm.compiler.core.GraalCompilerOptions.PrintFilter; 31 import static org.graalvm.compiler.core.GraalCompilerOptions.PrintStackTraceOnException; 32 import static org.graalvm.compiler.core.phases.HighTier.Options.Inline; 33 import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing; 34 35 import java.util.List; 36 37 import org.graalvm.compiler.code.CompilationResult; 38 import org.graalvm.compiler.debug.Debug; 39 import org.graalvm.compiler.debug.Debug.Scope; 40 import org.graalvm.compiler.debug.DebugCloseable; 41 import org.graalvm.compiler.debug.DebugCounter; 42 import org.graalvm.compiler.debug.DebugDumpScope; 43 import org.graalvm.compiler.debug.DebugTimer; 44 import org.graalvm.compiler.debug.GraalError; 45 import org.graalvm.compiler.debug.Management; 46 import org.graalvm.compiler.debug.TTY; 47 import org.graalvm.compiler.debug.TimeSource; 48 import org.graalvm.compiler.options.OptionKey; 49 import org.graalvm.compiler.options.OptionValues; 50 import org.graalvm.util.EconomicMap; 51 52 import jdk.vm.ci.code.BailoutException; 53 import jdk.vm.ci.code.CodeCacheProvider; 54 import jdk.vm.ci.hotspot.EventProvider; 55 import jdk.vm.ci.hotspot.HotSpotCompilationRequest; 56 import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; 57 import jdk.vm.ci.hotspot.HotSpotInstalledCode; 58 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; 59 import jdk.vm.ci.hotspot.HotSpotNmethod; 60 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; 61 import jdk.vm.ci.runtime.JVMCICompiler; 62 import jdk.vm.ci.services.JVMCIServiceLocator; 63 64 public class CompilationTask { 65 66 private static final DebugCounter BAILOUTS = Debug.counter("Bailouts"); 67 68 private static final EventProvider eventProvider; 69 70 static { 71 List<EventProvider> providers = JVMCIServiceLocator.getProviders(EventProvider.class); 72 if (providers.size() > 1) { 73 throw new GraalError("Multiple %s providers found: %s", EventProvider.class.getName(), providers); 74 } else if (providers.isEmpty()) { 75 eventProvider = EventProvider.createEmptyEventProvider(); 76 } else { 77 eventProvider = providers.get(0); 78 } 79 } 80 81 private final HotSpotJVMCIRuntimeProvider jvmciRuntime; 82 83 private final HotSpotGraalCompiler compiler; 84 private final HotSpotCompilationIdentifier compilationId; 85 86 private HotSpotInstalledCode installedCode; 87 88 /** 89 * Specifies whether the compilation result is installed as the 90 * {@linkplain HotSpotNmethod#isDefault() default} nmethod for the compiled method. 91 */ 92 private final boolean installAsDefault; 93 94 private final boolean useProfilingInfo; 95 private final OptionValues options; 96 97 final class RetryableCompilation extends HotSpotRetryableCompilation<HotSpotCompilationRequestResult> { 98 private final EventProvider.CompilationEvent compilationEvent; 99 CompilationResult result; 100 101 RetryableCompilation(EventProvider.CompilationEvent compilationEvent) { 102 super(compiler.getGraalRuntime(), options); 103 this.compilationEvent = compilationEvent; 104 } 105 106 @Override 107 public String toString() { 108 return getMethod().format("%H.%n"); 109 } 110 111 @SuppressWarnings("try") 112 @Override 113 protected HotSpotCompilationRequestResult run(Throwable retryCause) { 114 HotSpotResolvedJavaMethod method = getMethod(); 115 int entryBCI = getEntryBCI(); 116 final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; 117 CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR); 118 final boolean printCompilation = PrintCompilation.getValue(options) && !TTY.isSuppressed(); 119 final boolean printAfterCompilation = PrintAfterCompilation.getValue(options) && !TTY.isSuppressed(); 120 if (printCompilation) { 121 TTY.println(getMethodDescription() + "..."); 122 } 123 124 TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(options), method); 125 final long start; 126 final long allocatedBytesBefore; 127 if (printAfterCompilation || printCompilation) { 128 final long threadId = Thread.currentThread().getId(); 129 start = TimeSource.getTimeNS(); 130 allocatedBytesBefore = printAfterCompilation || printCompilation ? Lazy.threadMXBean.getThreadAllocatedBytes(threadId) : 0L; 131 } else { 132 start = 0L; 133 allocatedBytesBefore = 0L; 134 } 135 136 try (Scope s = Debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { 137 // Begin the compilation event. 138 compilationEvent.begin(); 139 result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId, options); 140 } catch (Throwable e) { 141 if (retryCause != null) { 142 log("Exception during retry", e); 143 } 144 throw Debug.handle(e); 145 } finally { 146 // End the compilation event. 147 compilationEvent.end(); 148 149 filter.remove(); 150 151 if (printAfterCompilation || printCompilation) { 152 final long threadId = Thread.currentThread().getId(); 153 final long stop = TimeSource.getTimeNS(); 154 final long duration = (stop - start) / 1000000; 155 final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1; 156 final int bytecodeSize = result != null ? result.getBytecodeSize() : 0; 157 final long allocatedBytesAfter = Lazy.threadMXBean.getThreadAllocatedBytes(threadId); 158 final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024; 159 160 if (printAfterCompilation) { 161 TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); 162 } else if (printCompilation) { 163 TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dB %5dkB", getId(), "", "", "", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); 164 } 165 } 166 } 167 168 if (result != null) { 169 try (DebugCloseable b = CodeInstallationTime.start()) { 170 installMethod(result); 171 } 172 } 173 stats.finish(method, installedCode); 174 if (result != null) { 175 return HotSpotCompilationRequestResult.success(result.getBytecodeSize() - method.getCodeSize()); 176 } 177 return null; 178 } 179 } 180 181 static class Lazy { 182 /** 183 * A {@link com.sun.management.ThreadMXBean} to be able to query some information about the 184 * current compiler thread, e.g. total allocated bytes. 185 */ 186 static final com.sun.management.ThreadMXBean threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean(); 187 } 188 189 public CompilationTask(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault, 190 OptionValues options) { 202 OptionValues newOptions = options; 203 if (!config.inline) { 204 EconomicMap<OptionKey<?>, Object> m = OptionValues.newOptionMap(); 205 if (Inline.getValue(options) && !Inline.hasBeenSet(options)) { 206 m.put(Inline, false); 207 } 208 if (InlineDuringParsing.getValue(options) && !InlineDuringParsing.hasBeenSet(options)) { 209 m.put(InlineDuringParsing, false); 210 } 211 if (!m.isEmpty()) { 212 newOptions = new OptionValues(options, m); 213 } 214 } 215 this.options = newOptions; 216 } 217 218 public HotSpotResolvedJavaMethod getMethod() { 219 return getRequest().getMethod(); 220 } 221 222 /** 223 * Returns the compilation id of this task. 224 * 225 * @return compile id 226 */ 227 public int getId() { 228 return getRequest().getId(); 229 } 230 231 public int getEntryBCI() { 232 return getRequest().getEntryBCI(); 233 } 234 235 /** 236 * @return the compilation id plus a trailing '%' is the compilation is an OSR to match 237 * PrintCompilation style output 238 */ 239 public String getIdString() { 240 if (getEntryBCI() != JVMCICompiler.INVOCATION_ENTRY_BCI) { 241 return getId() + "%"; 242 } else { 243 return Integer.toString(getId()); 244 } 245 } 246 247 public HotSpotInstalledCode getInstalledCode() { 248 return installedCode; 249 } 250 251 /** 252 * Time spent in compilation. 253 */ 254 private static final DebugTimer CompilationTime = Debug.timer("CompilationTime"); 255 256 /** 257 * Counts the number of compiled {@linkplain CompilationResult#getBytecodeSize() bytecodes}. 258 */ 259 private static final DebugCounter CompiledBytecodes = Debug.counter("CompiledBytecodes"); 260 261 /** 262 * Counts the number of compiled {@linkplain CompilationResult#getBytecodeSize() bytecodes} for 263 * which {@linkplain CompilationResult#getTargetCode()} code was installed. 264 */ 265 private static final DebugCounter CompiledAndInstalledBytecodes = Debug.counter("CompiledAndInstalledBytecodes"); 266 267 /** 268 * Counts the number of installed {@linkplain CompilationResult#getTargetCodeSize()} bytes. 269 */ 270 private static final DebugCounter InstalledCodeSize = Debug.counter("InstalledCodeSize"); 271 272 /** 273 * Time spent in code installation. 274 */ 275 public static final DebugTimer CodeInstallationTime = Debug.timer("CodeInstallation"); 276 277 @SuppressWarnings("try") 278 public HotSpotCompilationRequestResult runCompilation() { 279 HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime(); 280 GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); 281 int entryBCI = getEntryBCI(); 282 boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; 283 HotSpotResolvedJavaMethod method = getMethod(); 284 285 // register the compilation id in the method metrics 286 if (Debug.isMethodMeterEnabled()) { 287 if (getEntryBCI() != JVMCICompiler.INVOCATION_ENTRY_BCI) { 288 Debug.methodMetrics(method).addToMetric(getId(), "CompilationIdOSR"); 289 } else { 290 Debug.methodMetrics(method).addToMetric(getId(), "CompilationId"); 291 } 292 } 293 294 // Log a compilation event. 295 EventProvider.CompilationEvent compilationEvent = eventProvider.newCompilationEvent(); 296 297 if (installAsDefault) { 298 // If there is already compiled code for this method on our level we simply return. 299 // JVMCI compiles are always at the highest compile level, even in non-tiered mode so we 300 // only need to check for that value. 301 if (method.hasCodeAtLevel(entryBCI, config.compilationLevelFullOptimization)) { 302 return HotSpotCompilationRequestResult.failure("Already compiled", false); 303 } 304 } 305 306 RetryableCompilation compilation = new RetryableCompilation(compilationEvent); 307 try (DebugCloseable a = CompilationTime.start()) { 308 return compilation.execute(); 309 } catch (BailoutException bailout) { 310 BAILOUTS.increment(); 311 if (ExitVMOnBailout.getValue(options)) { 312 TTY.out.println(method.format("Bailout in %H.%n(%p)")); 313 bailout.printStackTrace(TTY.out); 314 System.exit(-1); 315 } else if (PrintBailout.getValue(options)) { 316 TTY.out.println(method.format("Bailout in %H.%n(%p)")); 317 bailout.printStackTrace(TTY.out); 318 } 319 /* 320 * Handling of permanent bailouts: Permanent bailouts that can happen for example due to 321 * unsupported unstructured control flow in the bytecodes of a method must not be 322 * retried. Hotspot compile broker will ensure that no recompilation at the given tier 323 * will happen if retry is false. 324 */ 325 final boolean permanentBailout = bailout.isPermanent(); 326 if (permanentBailout && PrintBailout.getValue(options)) { 327 TTY.println("Permanent bailout %s compiling method %s %s.", bailout.getMessage(), HotSpotGraalCompiler.str(method), (isOSR ? "OSR" : "")); 328 } 329 return HotSpotCompilationRequestResult.failure(bailout.getMessage(), !permanentBailout); 330 } catch (Throwable t) { 333 if (event.shouldWrite()) { 334 event.setCompileId(getId()); 335 event.setMessage(t.getMessage()); 336 event.commit(); 337 } 338 339 handleException(t); 340 /* 341 * Treat random exceptions from the compiler as indicating a problem compiling this 342 * method. Report the result of toString instead of getMessage to ensure that the 343 * exception type is included in the output in case there's no detail mesage. 344 */ 345 return HotSpotCompilationRequestResult.failure(t.toString(), false); 346 } finally { 347 try { 348 int compiledBytecodes = 0; 349 int codeSize = 0; 350 351 if (compilation.result != null) { 352 compiledBytecodes = compilation.result.getBytecodeSize(); 353 CompiledBytecodes.add(compiledBytecodes); 354 if (installedCode != null) { 355 codeSize = installedCode.getSize(); 356 CompiledAndInstalledBytecodes.add(compiledBytecodes); 357 InstalledCodeSize.add(codeSize); 358 } 359 } 360 361 // Log a compilation event. 362 if (compilationEvent.shouldWrite()) { 363 compilationEvent.setMethod(method.format("%H.%n(%p)")); 364 compilationEvent.setCompileId(getId()); 365 compilationEvent.setCompileLevel(config.compilationLevelFullOptimization); 366 compilationEvent.setSucceeded(compilation.result != null && installedCode != null); 367 compilationEvent.setIsOsr(isOSR); 368 compilationEvent.setCodeSize(codeSize); 369 compilationEvent.setInlinedBytes(compiledBytecodes); 370 compilationEvent.commit(); 371 } 372 } catch (Throwable t) { 373 handleException(t); 374 } 375 } 376 } 377 394 if (PrintStackTraceOnException.getValue(options) || exitVMOnException) { 395 try { 396 t.printStackTrace(TTY.out); 397 } catch (Throwable throwable) { 398 // Don't let an exception here change the other control flow 399 } 400 } 401 402 if (exitVMOnException) { 403 System.exit(-1); 404 } 405 } 406 407 private String getMethodDescription() { 408 HotSpotResolvedJavaMethod method = getMethod(); 409 return String.format("%-6d JVMCI %-70s %-45s %-50s %s", getId(), method.getDeclaringClass().getName(), method.getName(), method.getSignature().toMethodDescriptor(), 410 getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + getEntryBCI() + ") "); 411 } 412 413 @SuppressWarnings("try") 414 private void installMethod(final CompilationResult compResult) { 415 final CodeCacheProvider codeCache = jvmciRuntime.getHostJVMCIBackend().getCodeCache(); 416 HotSpotBackend backend = compiler.getGraalRuntime().getHostBackend(); 417 installedCode = null; 418 Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult}; 419 installedCode = (HotSpotInstalledCode) backend.createInstalledCode(getRequest().getMethod(), getRequest(), compResult, 420 getRequest().getMethod().getSpeculationLog(), null, installAsDefault, context); 421 } 422 423 @Override 424 public String toString() { 425 return "Compilation[id=" + getId() + ", " + getMethod().format("%H.%n(%p)") + (getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "@" + getEntryBCI()) + "]"; 426 } 427 428 private HotSpotCompilationRequest getRequest() { 429 return compilationId.getRequest(); 430 } 431 } | 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 package org.graalvm.compiler.hotspot; 24 25 import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnBailout; 26 import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException; 27 import static org.graalvm.compiler.core.GraalCompilerOptions.PrintAfterCompilation; 28 import static org.graalvm.compiler.core.GraalCompilerOptions.PrintBailout; 29 import static org.graalvm.compiler.core.GraalCompilerOptions.PrintCompilation; 30 import static org.graalvm.compiler.core.GraalCompilerOptions.PrintFilter; 31 import static org.graalvm.compiler.core.GraalCompilerOptions.PrintStackTraceOnException; 32 import static org.graalvm.compiler.core.phases.HighTier.Options.Inline; 33 import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing; 34 35 import java.util.List; 36 37 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 38 import org.graalvm.compiler.code.CompilationResult; 39 import org.graalvm.compiler.core.common.CompilationIdentifier; 40 import org.graalvm.compiler.debug.CounterKey; 41 import org.graalvm.compiler.debug.DebugCloseable; 42 import org.graalvm.compiler.debug.DebugContext; 43 import org.graalvm.compiler.debug.DebugDumpScope; 44 import org.graalvm.compiler.debug.GraalError; 45 import org.graalvm.compiler.debug.Management; 46 import org.graalvm.compiler.debug.TTY; 47 import org.graalvm.compiler.debug.TimeSource; 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 import org.graalvm.util.EconomicMap; 53 54 import jdk.vm.ci.code.BailoutException; 55 import jdk.vm.ci.code.CodeCacheProvider; 56 import jdk.vm.ci.hotspot.EventProvider; 57 import jdk.vm.ci.hotspot.HotSpotCompilationRequest; 58 import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; 59 import jdk.vm.ci.hotspot.HotSpotInstalledCode; 60 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; 61 import jdk.vm.ci.hotspot.HotSpotNmethod; 62 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; 63 import jdk.vm.ci.runtime.JVMCICompiler; 64 import jdk.vm.ci.services.JVMCIServiceLocator; 65 66 public class CompilationTask { 67 68 private static final CounterKey BAILOUTS = DebugContext.counter("Bailouts"); 69 70 private static final EventProvider eventProvider; 71 72 static { 73 List<EventProvider> providers = JVMCIServiceLocator.getProviders(EventProvider.class); 74 if (providers.size() > 1) { 75 throw new GraalError("Multiple %s providers found: %s", EventProvider.class.getName(), providers); 76 } else if (providers.isEmpty()) { 77 eventProvider = EventProvider.createEmptyEventProvider(); 78 } else { 79 eventProvider = providers.get(0); 80 } 81 } 82 83 private final HotSpotJVMCIRuntimeProvider jvmciRuntime; 84 85 private final HotSpotGraalCompiler compiler; 86 private final HotSpotCompilationIdentifier compilationId; 87 88 private HotSpotInstalledCode installedCode; 89 90 /** 91 * Specifies whether the compilation result is installed as the 92 * {@linkplain HotSpotNmethod#isDefault() default} nmethod for the compiled method. 93 */ 94 private final boolean installAsDefault; 95 96 private final boolean useProfilingInfo; 97 private final OptionValues options; 98 99 final class RetryableCompilation extends HotSpotRetryableCompilation<HotSpotCompilationRequestResult> { 100 private final EventProvider.CompilationEvent compilationEvent; 101 CompilationResult result; 102 103 RetryableCompilation(EventProvider.CompilationEvent compilationEvent) { 104 super(compiler.getGraalRuntime()); 105 this.compilationEvent = compilationEvent; 106 } 107 108 @Override 109 public String toString() { 110 return getMethod().format("%H.%n"); 111 } 112 113 @SuppressWarnings("try") 114 @Override 115 protected HotSpotCompilationRequestResult run(DebugContext debug, Throwable retryCause) { 116 HotSpotResolvedJavaMethod method = getMethod(); 117 int entryBCI = getEntryBCI(); 118 final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; 119 CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR); 120 final boolean printCompilation = PrintCompilation.getValue(options) && !TTY.isSuppressed(); 121 final boolean printAfterCompilation = PrintAfterCompilation.getValue(options) && !TTY.isSuppressed(); 122 if (printCompilation) { 123 TTY.println(getMethodDescription() + "..."); 124 } 125 126 TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(options), method); 127 final long start; 128 final long allocatedBytesBefore; 129 if (printAfterCompilation || printCompilation) { 130 final long threadId = Thread.currentThread().getId(); 131 start = TimeSource.getTimeNS(); 132 allocatedBytesBefore = printAfterCompilation || printCompilation ? Lazy.threadMXBean.getThreadAllocatedBytes(threadId) : 0L; 133 } else { 134 start = 0L; 135 allocatedBytesBefore = 0L; 136 } 137 138 try (DebugContext.Scope s = debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { 139 // Begin the compilation event. 140 compilationEvent.begin(); 141 result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId, options, debug); 142 } catch (Throwable e) { 143 if (retryCause != null) { 144 log("Exception during retry", e); 145 } 146 throw debug.handle(e); 147 } finally { 148 // End the compilation event. 149 compilationEvent.end(); 150 151 filter.remove(); 152 153 if (printAfterCompilation || printCompilation) { 154 final long threadId = Thread.currentThread().getId(); 155 final long stop = TimeSource.getTimeNS(); 156 final long duration = (stop - start) / 1000000; 157 final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1; 158 final int bytecodeSize = result != null ? result.getBytecodeSize() : 0; 159 final long allocatedBytesAfter = Lazy.threadMXBean.getThreadAllocatedBytes(threadId); 160 final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024; 161 162 if (printAfterCompilation) { 163 TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); 164 } else if (printCompilation) { 165 TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dB %5dkB", getId(), "", "", "", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); 166 } 167 } 168 } 169 170 if (result != null) { 171 try (DebugCloseable b = CodeInstallationTime.start(debug)) { 172 installMethod(debug, result); 173 } 174 } 175 stats.finish(method, installedCode); 176 if (result != null) { 177 return HotSpotCompilationRequestResult.success(result.getBytecodeSize() - method.getCodeSize()); 178 } 179 return null; 180 } 181 } 182 183 static class Lazy { 184 /** 185 * A {@link com.sun.management.ThreadMXBean} to be able to query some information about the 186 * current compiler thread, e.g. total allocated bytes. 187 */ 188 static final com.sun.management.ThreadMXBean threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean(); 189 } 190 191 public CompilationTask(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault, 192 OptionValues options) { 204 OptionValues newOptions = options; 205 if (!config.inline) { 206 EconomicMap<OptionKey<?>, Object> m = OptionValues.newOptionMap(); 207 if (Inline.getValue(options) && !Inline.hasBeenSet(options)) { 208 m.put(Inline, false); 209 } 210 if (InlineDuringParsing.getValue(options) && !InlineDuringParsing.hasBeenSet(options)) { 211 m.put(InlineDuringParsing, false); 212 } 213 if (!m.isEmpty()) { 214 newOptions = new OptionValues(options, m); 215 } 216 } 217 this.options = newOptions; 218 } 219 220 public HotSpotResolvedJavaMethod getMethod() { 221 return getRequest().getMethod(); 222 } 223 224 CompilationIdentifier getCompilationIdentifier() { 225 return compilationId; 226 } 227 228 /** 229 * Returns the HostSpot id of this compilation. 230 * 231 * @return HotSpot compile id 232 */ 233 public int getId() { 234 return getRequest().getId(); 235 } 236 237 public int getEntryBCI() { 238 return getRequest().getEntryBCI(); 239 } 240 241 /** 242 * @return the compilation id plus a trailing '%' is the compilation is an OSR to match 243 * PrintCompilation style output 244 */ 245 public String getIdString() { 246 if (getEntryBCI() != JVMCICompiler.INVOCATION_ENTRY_BCI) { 247 return getId() + "%"; 248 } else { 249 return Integer.toString(getId()); 250 } 251 } 252 253 public HotSpotInstalledCode getInstalledCode() { 254 return installedCode; 255 } 256 257 /** 258 * Time spent in compilation. 259 */ 260 private static final TimerKey CompilationTime = DebugContext.timer("CompilationTime").doc("Time spent in compilation and code installation."); 261 262 /** 263 * Counts the number of compiled {@linkplain CompilationResult#getBytecodeSize() bytecodes}. 264 */ 265 private static final CounterKey CompiledBytecodes = DebugContext.counter("CompiledBytecodes"); 266 267 /** 268 * Counts the number of compiled {@linkplain CompilationResult#getBytecodeSize() bytecodes} for 269 * which {@linkplain CompilationResult#getTargetCode()} code was installed. 270 */ 271 private static final CounterKey CompiledAndInstalledBytecodes = DebugContext.counter("CompiledAndInstalledBytecodes"); 272 273 /** 274 * Counts the number of installed {@linkplain CompilationResult#getTargetCodeSize()} bytes. 275 */ 276 private static final CounterKey InstalledCodeSize = DebugContext.counter("InstalledCodeSize"); 277 278 /** 279 * Time spent in code installation. 280 */ 281 public static final TimerKey CodeInstallationTime = DebugContext.timer("CodeInstallation"); 282 283 public HotSpotCompilationRequestResult runCompilation() { 284 SnippetReflectionProvider snippetReflection = compiler.getGraalRuntime().getHostProviders().getSnippetReflection(); 285 try (DebugContext debug = DebugContext.create(options, new GraalDebugHandlersFactory(snippetReflection))) { 286 return runCompilation(debug); 287 } 288 } 289 290 @SuppressWarnings("try") 291 public HotSpotCompilationRequestResult runCompilation(DebugContext debug) { 292 HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime(); 293 GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); 294 int entryBCI = getEntryBCI(); 295 boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; 296 HotSpotResolvedJavaMethod method = getMethod(); 297 298 // Log a compilation event. 299 EventProvider.CompilationEvent compilationEvent = eventProvider.newCompilationEvent(); 300 301 if (installAsDefault) { 302 // If there is already compiled code for this method on our level we simply return. 303 // JVMCI compiles are always at the highest compile level, even in non-tiered mode so we 304 // only need to check for that value. 305 if (method.hasCodeAtLevel(entryBCI, config.compilationLevelFullOptimization)) { 306 return HotSpotCompilationRequestResult.failure("Already compiled", false); 307 } 308 } 309 310 RetryableCompilation compilation = new RetryableCompilation(compilationEvent); 311 try (DebugCloseable a = CompilationTime.start(debug)) { 312 return compilation.runWithRetry(debug); 313 } catch (BailoutException bailout) { 314 BAILOUTS.increment(debug); 315 if (ExitVMOnBailout.getValue(options)) { 316 TTY.out.println(method.format("Bailout in %H.%n(%p)")); 317 bailout.printStackTrace(TTY.out); 318 System.exit(-1); 319 } else if (PrintBailout.getValue(options)) { 320 TTY.out.println(method.format("Bailout in %H.%n(%p)")); 321 bailout.printStackTrace(TTY.out); 322 } 323 /* 324 * Handling of permanent bailouts: Permanent bailouts that can happen for example due to 325 * unsupported unstructured control flow in the bytecodes of a method must not be 326 * retried. Hotspot compile broker will ensure that no recompilation at the given tier 327 * will happen if retry is false. 328 */ 329 final boolean permanentBailout = bailout.isPermanent(); 330 if (permanentBailout && PrintBailout.getValue(options)) { 331 TTY.println("Permanent bailout %s compiling method %s %s.", bailout.getMessage(), HotSpotGraalCompiler.str(method), (isOSR ? "OSR" : "")); 332 } 333 return HotSpotCompilationRequestResult.failure(bailout.getMessage(), !permanentBailout); 334 } catch (Throwable t) { 337 if (event.shouldWrite()) { 338 event.setCompileId(getId()); 339 event.setMessage(t.getMessage()); 340 event.commit(); 341 } 342 343 handleException(t); 344 /* 345 * Treat random exceptions from the compiler as indicating a problem compiling this 346 * method. Report the result of toString instead of getMessage to ensure that the 347 * exception type is included in the output in case there's no detail mesage. 348 */ 349 return HotSpotCompilationRequestResult.failure(t.toString(), false); 350 } finally { 351 try { 352 int compiledBytecodes = 0; 353 int codeSize = 0; 354 355 if (compilation.result != null) { 356 compiledBytecodes = compilation.result.getBytecodeSize(); 357 CompiledBytecodes.add(debug, compiledBytecodes); 358 if (installedCode != null) { 359 codeSize = installedCode.getSize(); 360 CompiledAndInstalledBytecodes.add(debug, compiledBytecodes); 361 InstalledCodeSize.add(debug, codeSize); 362 } 363 } 364 365 // Log a compilation event. 366 if (compilationEvent.shouldWrite()) { 367 compilationEvent.setMethod(method.format("%H.%n(%p)")); 368 compilationEvent.setCompileId(getId()); 369 compilationEvent.setCompileLevel(config.compilationLevelFullOptimization); 370 compilationEvent.setSucceeded(compilation.result != null && installedCode != null); 371 compilationEvent.setIsOsr(isOSR); 372 compilationEvent.setCodeSize(codeSize); 373 compilationEvent.setInlinedBytes(compiledBytecodes); 374 compilationEvent.commit(); 375 } 376 } catch (Throwable t) { 377 handleException(t); 378 } 379 } 380 } 381 398 if (PrintStackTraceOnException.getValue(options) || exitVMOnException) { 399 try { 400 t.printStackTrace(TTY.out); 401 } catch (Throwable throwable) { 402 // Don't let an exception here change the other control flow 403 } 404 } 405 406 if (exitVMOnException) { 407 System.exit(-1); 408 } 409 } 410 411 private String getMethodDescription() { 412 HotSpotResolvedJavaMethod method = getMethod(); 413 return String.format("%-6d JVMCI %-70s %-45s %-50s %s", getId(), method.getDeclaringClass().getName(), method.getName(), method.getSignature().toMethodDescriptor(), 414 getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + getEntryBCI() + ") "); 415 } 416 417 @SuppressWarnings("try") 418 private void installMethod(DebugContext debug, final CompilationResult compResult) { 419 final CodeCacheProvider codeCache = jvmciRuntime.getHostJVMCIBackend().getCodeCache(); 420 HotSpotBackend backend = compiler.getGraalRuntime().getHostBackend(); 421 installedCode = null; 422 Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult}; 423 try (DebugContext.Scope s = debug.scope("CodeInstall", context)) { 424 installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug, getRequest().getMethod(), getRequest(), compResult, 425 getRequest().getMethod().getSpeculationLog(), null, installAsDefault, context); 426 } catch (Throwable e) { 427 throw debug.handle(e); 428 } 429 } 430 431 @Override 432 public String toString() { 433 return "Compilation[id=" + getId() + ", " + getMethod().format("%H.%n(%p)") + (getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "@" + getEntryBCI()) + "]"; 434 } 435 436 private HotSpotCompilationRequest getRequest() { 437 return compilationId.getRequest(); 438 } 439 } |