1 /* 2 * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 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 jdk.vm.ci.common.InitTimer.timer; 28 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; 29 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; 30 import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; 31 32 import java.io.PrintStream; 33 import java.util.ArrayList; 34 import java.util.EnumMap; 35 import java.util.List; 36 import java.util.Map; 37 import java.util.concurrent.atomic.AtomicReference; 38 39 import jdk.internal.vm.compiler.collections.EconomicMap; 40 import jdk.internal.vm.compiler.collections.EconomicSet; 41 import jdk.internal.vm.compiler.collections.Equivalence; 42 import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor; 43 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 44 import org.graalvm.compiler.api.runtime.GraalRuntime; 45 import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction; 46 import org.graalvm.compiler.core.common.CompilationIdentifier; 47 import org.graalvm.compiler.core.common.GraalOptions; 48 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; 49 import org.graalvm.compiler.core.target.Backend; 50 import org.graalvm.compiler.debug.DebugContext; 51 import org.graalvm.compiler.debug.DebugContext.Description; 52 import org.graalvm.compiler.debug.DebugHandlersFactory; 53 import org.graalvm.compiler.debug.DebugOptions; 54 import org.graalvm.compiler.debug.DiagnosticsOutputDirectory; 55 import org.graalvm.compiler.debug.GlobalMetrics; 56 import org.graalvm.compiler.debug.GraalError; 57 import org.graalvm.compiler.debug.TTY; 58 import org.graalvm.compiler.hotspot.CompilationStatistics.Options; 59 import org.graalvm.compiler.hotspot.CompilerConfigurationFactory.BackendMap; 60 import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; 61 import org.graalvm.compiler.hotspot.meta.HotSpotProviders; 62 import org.graalvm.compiler.nodes.spi.StampProvider; 63 import org.graalvm.compiler.options.EnumOptionKey; 64 import org.graalvm.compiler.options.OptionDescriptor; 65 import org.graalvm.compiler.options.OptionDescriptors; 66 import org.graalvm.compiler.options.OptionKey; 67 import org.graalvm.compiler.options.OptionValues; 68 import org.graalvm.compiler.options.OptionsParser; 69 import org.graalvm.compiler.phases.tiers.CompilerConfiguration; 70 import org.graalvm.compiler.replacements.SnippetCounter; 71 import org.graalvm.compiler.replacements.SnippetCounter.Group; 72 import org.graalvm.compiler.runtime.RuntimeProvider; 73 import org.graalvm.compiler.serviceprovider.GraalServices; 74 75 import jdk.vm.ci.code.Architecture; 76 import jdk.vm.ci.code.stack.StackIntrospection; 77 import jdk.vm.ci.common.InitTimer; 78 import jdk.vm.ci.hotspot.HotSpotCompilationRequest; 79 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; 80 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; 81 import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; 82 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; 83 import jdk.vm.ci.hotspot.HotSpotVMConfigStore; 84 import jdk.vm.ci.meta.JavaKind; 85 import jdk.vm.ci.meta.MetaAccessProvider; 86 import jdk.vm.ci.meta.ResolvedJavaMethod; 87 import jdk.vm.ci.meta.ResolvedJavaType; 88 import jdk.vm.ci.runtime.JVMCI; 89 import jdk.vm.ci.runtime.JVMCIBackend; 90 import jdk.vm.ci.services.Services; 91 92 //JaCoCo Exclude 93 94 /** 95 * Singleton class holding the instance of the {@link GraalRuntime}. 96 */ 97 public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { 98 99 private static final boolean IS_AOT = Boolean.parseBoolean(Services.getSavedProperties().get("com.oracle.graalvm.isaot")); 100 101 private static boolean checkArrayIndexScaleInvariants(MetaAccessProvider metaAccess) { 102 assert metaAccess.getArrayIndexScale(JavaKind.Byte) == 1; 103 assert metaAccess.getArrayIndexScale(JavaKind.Boolean) == 1; 104 assert metaAccess.getArrayIndexScale(JavaKind.Char) == 2; 105 assert metaAccess.getArrayIndexScale(JavaKind.Short) == 2; 106 assert metaAccess.getArrayIndexScale(JavaKind.Int) == 4; 107 assert metaAccess.getArrayIndexScale(JavaKind.Long) == 8; 108 assert metaAccess.getArrayIndexScale(JavaKind.Float) == 4; 109 assert metaAccess.getArrayIndexScale(JavaKind.Double) == 8; 110 return true; 111 } 112 113 private final String runtimeName; 114 private final String compilerConfigurationName; 115 private final HotSpotBackend hostBackend; 116 117 public GlobalMetrics getMetricValues() { 118 return metricValues; 119 } 120 121 private final GlobalMetrics metricValues = new GlobalMetrics(); 122 private final List<SnippetCounter.Group> snippetCounterGroups; 123 private final HotSpotGC garbageCollector; 124 125 private final EconomicMap<Class<? extends Architecture>, HotSpotBackend> backends = EconomicMap.create(Equivalence.IDENTITY); 126 127 private final GraalHotSpotVMConfig config; 128 129 /** 130 * The options can be {@linkplain #setOptionValues(String[], String[]) updated} by external 131 * interfaces such as JMX. This comes with the risk that inconsistencies can arise as an 132 * {@link OptionValues} object can be cached by various parts of Graal instead of always 133 * obtaining them from this object. However, concurrent updates are never lost. 134 */ 135 private AtomicReference<OptionValues> optionsRef = new AtomicReference<>(); 136 137 private final DiagnosticsOutputDirectory outputDirectory; 138 private final Map<ExceptionAction, Integer> compilationProblemsPerAction; 139 140 /** 141 * @param nameQualifier a qualifier to be added to this runtime's {@linkplain #getName() name} 142 * @param compilerConfigurationFactory factory for the compiler configuration 143 * {@link CompilerConfigurationFactory#selectFactory(String, OptionValues)} 144 */ 145 @SuppressWarnings("try") 146 HotSpotGraalRuntime(String nameQualifier, HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory, OptionValues initialOptions) { 147 this.runtimeName = getClass().getSimpleName() + ":" + nameQualifier; 148 HotSpotVMConfigStore store = jvmciRuntime.getConfigStore(); 149 config = GeneratePIC.getValue(initialOptions) ? new AOTGraalHotSpotVMConfig(store) : new GraalHotSpotVMConfig(store); 150 151 // Only set HotSpotPrintInlining if it still has its default value (false). 152 if (GraalOptions.HotSpotPrintInlining.getValue(initialOptions) == false && config.printInlining) { 153 optionsRef.set(new OptionValues(initialOptions, HotSpotPrintInlining, true)); 154 } else { 155 optionsRef.set(initialOptions); 156 } 157 OptionValues options = optionsRef.get(); 158 159 garbageCollector = getSelectedGC(); 160 161 outputDirectory = new DiagnosticsOutputDirectory(options); 162 compilationProblemsPerAction = new EnumMap<>(ExceptionAction.class); 163 snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null; 164 CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration(); 165 compilerConfigurationName = compilerConfigurationFactory.getName(); 166 167 if (IS_AOT) { 168 management = null; 169 } else { 170 management = GraalServices.loadSingle(HotSpotGraalManagementRegistration.class, false); 171 if (management != null) { 172 management.initialize(this); 173 } 174 } 175 176 BackendMap backendMap = compilerConfigurationFactory.createBackendMap(); 177 178 JVMCIBackend hostJvmciBackend = jvmciRuntime.getHostJVMCIBackend(); 179 Architecture hostArchitecture = hostJvmciBackend.getTarget().arch; 180 try (InitTimer t = timer("create backend:", hostArchitecture)) { 181 HotSpotBackendFactory factory = backendMap.getBackendFactory(hostArchitecture); 182 if (factory == null) { 183 throw new GraalError("No backend available for host architecture \"%s\"", hostArchitecture); 184 } 185 hostBackend = registerBackend(factory.createBackend(this, compilerConfiguration, jvmciRuntime, null)); 186 } 187 188 for (JVMCIBackend jvmciBackend : jvmciRuntime.getJVMCIBackends().values()) { 189 if (jvmciBackend == hostJvmciBackend) { 190 continue; 191 } 192 193 Architecture gpuArchitecture = jvmciBackend.getTarget().arch; 194 HotSpotBackendFactory factory = backendMap.getBackendFactory(gpuArchitecture); 195 if (factory == null) { 196 throw new GraalError("No backend available for specified GPU architecture \"%s\"", gpuArchitecture); 197 } 198 try (InitTimer t = timer("create backend:", gpuArchitecture)) { 199 registerBackend(factory.createBackend(this, compilerConfiguration, null, hostBackend)); 200 } 201 } 202 203 // Complete initialization of backends 204 try (InitTimer st = timer(hostBackend.getTarget().arch.getName(), ".completeInitialization")) { 205 hostBackend.completeInitialization(jvmciRuntime, options); 206 } 207 for (HotSpotBackend backend : backends.getValues()) { 208 if (backend != hostBackend) { 209 try (InitTimer st = timer(backend.getTarget().arch.getName(), ".completeInitialization")) { 210 backend.completeInitialization(jvmciRuntime, options); 211 } 212 } 213 } 214 215 BenchmarkCounters.initialize(jvmciRuntime, options); 216 217 assert checkArrayIndexScaleInvariants(hostJvmciBackend.getMetaAccess()); 218 219 runtimeStartTime = System.nanoTime(); 220 bootstrapJVMCI = config.getFlag("BootstrapJVMCI", Boolean.class); 221 } 222 223 /** 224 * Constants denoting the GC algorithms available in HotSpot. 225 */ 226 public enum HotSpotGC { 227 // Supported GCs 228 Serial(true, "UseSerialGC"), 229 Parallel(true, "UseParallelGC", "UseParallelOldGC", "UseParNewGC"), 230 CMS(true, "UseConcMarkSweepGC"), 231 G1(true, "UseG1GC"), 232 233 // Unsupported GCs 234 Epsilon(false, "UseEpsilonGC"), 235 Z(false, "UseZGC"); 236 237 HotSpotGC(boolean supported, String... flags) { 238 this.supported = supported; 239 this.flags = flags; 240 } 241 242 final boolean supported; 243 private final String[] flags; 244 245 public boolean isSelected(GraalHotSpotVMConfig config) { 246 for (String flag : flags) { 247 final boolean notPresent = false; 248 if (config.getFlag(flag, Boolean.class, notPresent)) { 249 return true; 250 } 251 } 252 return false; 253 } 254 255 } 256 257 private HotSpotGC getSelectedGC() throws GraalError { 258 for (HotSpotGC gc : HotSpotGC.values()) { 259 if (gc.isSelected(config)) { 260 if (!gc.supported) { 261 throw new GraalError(gc.name() + " garbage collector is not supported by Graal"); 262 } 263 return gc; 264 } 265 } 266 // As of JDK 9, exactly one GC flag is guaranteed to be selected. 267 // On JDK 8, the default GC is Serial when no GC flag is true. 268 return HotSpotGC.Serial; 269 } 270 271 private HotSpotBackend registerBackend(HotSpotBackend backend) { 272 Class<? extends Architecture> arch = backend.getTarget().arch.getClass(); 273 HotSpotBackend oldValue = backends.put(arch, backend); 274 assert oldValue == null : "cannot overwrite existing backend for architecture " + arch.getSimpleName(); 275 return backend; 276 } 277 278 @Override 279 public HotSpotProviders getHostProviders() { 280 return getHostBackend().getProviders(); 281 } 282 283 @Override 284 public GraalHotSpotVMConfig getVMConfig() { 285 return config; 286 } 287 288 @Override 289 public DebugContext openDebugContext(OptionValues compilationOptions, CompilationIdentifier compilationId, Object compilable, Iterable<DebugHandlersFactory> factories, PrintStream logStream) { 290 if (management != null && management.poll(false) != null) { 291 if (compilable instanceof HotSpotResolvedJavaMethod) { 292 HotSpotResolvedObjectType type = ((HotSpotResolvedJavaMethod) compilable).getDeclaringClass(); 293 if (type instanceof HotSpotResolvedJavaType) { 294 Class<?> clazz = runtime().getMirror(type); 295 try { 296 ClassLoader cl = clazz.getClassLoader(); 297 if (cl != null) { 298 loaders.add(cl); 299 } 300 } catch (SecurityException e) { 301 // This loader can obviously not be used for resolving class names 302 } 303 } 304 } 305 } 306 Description description = new Description(compilable, compilationId.toString(CompilationIdentifier.Verbosity.ID)); 307 return DebugContext.create(compilationOptions, description, metricValues, logStream, factories); 308 } 309 310 @Override 311 public OptionValues getOptions() { 312 return optionsRef.get(); 313 } 314 315 @Override 316 public Group createSnippetCounterGroup(String groupName) { 317 if (snippetCounterGroups != null) { 318 Group group = new Group(groupName); 319 snippetCounterGroups.add(group); 320 return group; 321 } 322 return null; 323 } 324 325 @Override 326 public String getName() { 327 return runtimeName; 328 } 329 330 @SuppressWarnings("unchecked") 331 @Override 332 public <T> T getCapability(Class<T> clazz) { 333 if (clazz == RuntimeProvider.class) { 334 return (T) this; 335 } else if (clazz == OptionValues.class) { 336 return (T) optionsRef.get(); 337 } else if (clazz == StackIntrospection.class) { 338 return (T) this; 339 } else if (clazz == SnippetReflectionProvider.class) { 340 return (T) getHostProviders().getSnippetReflection(); 341 } else if (clazz == GraalHotSpotVMConfig.class) { 342 return (T) getVMConfig(); 343 } else if (clazz == StampProvider.class) { 344 return (T) getHostProviders().getStampProvider(); 345 } else if (ForeignCallsProvider.class.isAssignableFrom(clazz)) { 346 return (T) getHostProviders().getForeignCalls(); 347 } 348 return null; 349 } 350 351 public HotSpotGC getGarbageCollector() { 352 return garbageCollector; 353 } 354 355 @Override 356 public HotSpotBackend getHostBackend() { 357 return hostBackend; 358 } 359 360 @Override 361 public <T extends Architecture> Backend getBackend(Class<T> arch) { 362 assert arch != Architecture.class; 363 return backends.get(arch); 364 } 365 366 @Override 367 public String getCompilerConfigurationName() { 368 return compilerConfigurationName; 369 } 370 371 private long runtimeStartTime; 372 373 /** 374 * Called from compiler threads to check whether to bail out of a compilation. 375 */ 376 private volatile boolean shutdown; 377 378 /** 379 * Take action related to entering a new execution phase. 380 * 381 * @param phase the execution phase being entered 382 */ 383 void phaseTransition(String phase) { 384 if (Options.UseCompilationStatistics.getValue(optionsRef.get())) { 385 CompilationStatistics.clear(phase); 386 } 387 } 388 389 void shutdown() { 390 shutdown = true; 391 metricValues.print(optionsRef.get()); 392 393 phaseTransition("final"); 394 395 if (snippetCounterGroups != null) { 396 for (Group group : snippetCounterGroups) { 397 TTY.out().out().println(group); 398 } 399 } 400 BenchmarkCounters.shutdown(runtime(), optionsRef.get(), runtimeStartTime); 401 402 outputDirectory.close(); 403 404 shutdownLibGraal(); 405 } 406 407 /** 408 * Substituted by 409 * {@code com.oracle.svm.graal.hotspot.libgraal.Target_org_graalvm_compiler_hotspot_HotSpotGraalRuntime} 410 * to call {@code org.graalvm.nativeimage.VMRuntime.shutdown()}. 411 */ 412 private static void shutdownLibGraal() { 413 } 414 415 void clearMetrics() { 416 metricValues.clear(); 417 } 418 419 private final boolean bootstrapJVMCI; 420 private boolean bootstrapFinished; 421 422 public void notifyBootstrapFinished() { 423 bootstrapFinished = true; 424 } 425 426 @Override 427 public boolean isBootstrapping() { 428 return bootstrapJVMCI && !bootstrapFinished; 429 } 430 431 @Override 432 public boolean isShutdown() { 433 return shutdown; 434 } 435 436 @Override 437 public DiagnosticsOutputDirectory getOutputDirectory() { 438 return outputDirectory; 439 } 440 441 @Override 442 public Map<ExceptionAction, Integer> getCompilationProblemsPerAction() { 443 return compilationProblemsPerAction; 444 } 445 446 // ------- Management interface --------- 447 448 private final HotSpotGraalManagementRegistration management; 449 450 /** 451 * @returns the management object for this runtime or {@code null} 452 */ 453 public HotSpotGraalManagementRegistration getManagement() { 454 return management; 455 } 456 457 /** 458 * Set of weak references to {@link ClassLoader}s available for resolving class names present in 459 * management {@linkplain #invokeManagementAction(String, Object[]) action} arguments. 460 */ 461 private final WeakClassLoaderSet loaders = new WeakClassLoaderSet(ClassLoader.getSystemClassLoader()); 462 463 /** 464 * Sets or updates this object's {@linkplain #getOptions() options} from {@code names} and 465 * {@code values}. 466 * 467 * @param values the values to set. The empty string represents {@code null} which resets an 468 * option to its default value. For string type options, a non-empty value must be 469 * enclosed in double quotes. 470 * @return an array of Strings where the element at index i is {@code names[i]} if setting the 471 * denoted option succeeded, {@code null} if the option is unknown otherwise an error 472 * message describing the failure to set the option 473 */ 474 public String[] setOptionValues(String[] names, String[] values) { 475 EconomicMap<String, OptionDescriptor> optionDescriptors = getOptionDescriptors(); 476 EconomicMap<OptionKey<?>, Object> newValues = EconomicMap.create(names.length); 477 EconomicSet<OptionKey<?>> resetValues = EconomicSet.create(names.length); 478 String[] result = new String[names.length]; 479 for (int i = 0; i < names.length; i++) { 480 String name = names[i]; 481 OptionDescriptor option = optionDescriptors.get(name); 482 if (option != null) { 483 String svalue = values[i]; 484 Class<?> optionValueType = option.getOptionValueType(); 485 OptionKey<?> optionKey = option.getOptionKey(); 486 if (svalue == null || svalue.isEmpty() && !(optionKey instanceof EnumOptionKey)) { 487 resetValues.add(optionKey); 488 result[i] = name; 489 } else { 490 String valueToParse; 491 if (optionValueType == String.class) { 492 if (svalue.length() < 2 || svalue.charAt(0) != '"' || svalue.charAt(svalue.length() - 1) != '"') { 493 result[i] = "Invalid value for String option '" + name + "': must be the empty string or be enclosed in double quotes: " + svalue; 494 continue; 495 } else { 496 valueToParse = svalue.substring(1, svalue.length() - 1); 497 } 498 } else { 499 valueToParse = svalue; 500 } 501 try { 502 OptionsParser.parseOption(name, valueToParse, newValues, OptionsParser.getOptionsLoader()); 503 result[i] = name; 504 } catch (IllegalArgumentException e) { 505 result[i] = e.getMessage(); 506 continue; 507 } 508 } 509 } else { 510 result[i] = null; 511 } 512 } 513 514 OptionValues currentOptions; 515 OptionValues newOptions; 516 do { 517 currentOptions = optionsRef.get(); 518 UnmodifiableMapCursor<OptionKey<?>, Object> cursor = currentOptions.getMap().getEntries(); 519 while (cursor.advance()) { 520 OptionKey<?> key = cursor.getKey(); 521 if (!resetValues.contains(key) && !newValues.containsKey(key)) { 522 newValues.put(key, OptionValues.decodeNull(cursor.getValue())); 523 } 524 } 525 newOptions = new OptionValues(newValues); 526 } while (!optionsRef.compareAndSet(currentOptions, newOptions)); 527 528 return result; 529 } 530 531 /** 532 * Gets the values for the options corresponding to {@code names} encoded as strings. The empty 533 * string represents {@code null}. For string type options, non-{@code null} values will be 534 * enclosed in double quotes. 535 * 536 * @param names a list of option names 537 * @return the values for each named option. If an element in {@code names} does not denote an 538 * existing option, the corresponding element in the returned array will be {@code null} 539 */ 540 public String[] getOptionValues(String... names) { 541 String[] values = new String[names.length]; 542 EconomicMap<String, OptionDescriptor> optionDescriptors = getOptionDescriptors(); 543 for (int i = 0; i < names.length; i++) { 544 OptionDescriptor option = optionDescriptors.get(names[i]); 545 if (option != null) { 546 OptionKey<?> optionKey = option.getOptionKey(); 547 Object value = optionKey.getValue(getOptions()); 548 String svalue; 549 if (option.getOptionValueType() == String.class && value != null) { 550 svalue = "\"" + value + "\""; 551 } else if (value == null) { 552 svalue = ""; 553 } else { 554 svalue = String.valueOf(value); 555 } 556 values[i] = svalue; 557 } else { 558 // null denotes the option does not exist 559 values[i] = null; 560 } 561 } 562 return values; 563 } 564 565 private static EconomicMap<String, OptionDescriptor> getOptionDescriptors() { 566 EconomicMap<String, OptionDescriptor> result = EconomicMap.create(); 567 for (OptionDescriptors set : OptionsParser.getOptionsLoader()) { 568 for (OptionDescriptor option : set) { 569 result.put(option.getName(), option); 570 } 571 } 572 return result; 573 } 574 575 private void dumpMethod(String className, String methodName, String filter, String host, int port) throws Exception { 576 EconomicSet<ClassNotFoundException> failures = EconomicSet.create(); 577 EconomicSet<Class<?>> found = loaders.resolve(className, failures); 578 if (found.isEmpty()) { 579 ClassNotFoundException cause = failures.isEmpty() ? new ClassNotFoundException(className) : failures.iterator().next(); 580 throw new Exception("Cannot find class " + className + " to schedule recompilation", cause); 581 } 582 for (Class<?> clazz : found) { 583 ResolvedJavaType type = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaType(clazz); 584 for (ResolvedJavaMethod method : type.getDeclaredMethods()) { 585 if (methodName.equals(method.getName()) && method instanceof HotSpotResolvedJavaMethod) { 586 HotSpotResolvedJavaMethod hotSpotMethod = (HotSpotResolvedJavaMethod) method; 587 dumpMethod(hotSpotMethod, filter, host, port); 588 } 589 } 590 } 591 } 592 593 private void dumpMethod(HotSpotResolvedJavaMethod hotSpotMethod, String filter, String host, int port) throws Exception { 594 EconomicMap<OptionKey<?>, Object> extra = EconomicMap.create(); 595 extra.put(DebugOptions.Dump, filter); 596 extra.put(DebugOptions.PrintGraphHost, host); 597 extra.put(DebugOptions.PrintGraphPort, port); 598 OptionValues compileOptions = new OptionValues(getOptions(), extra); 599 HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime().getCompiler(); 600 compiler.compileMethod(new HotSpotCompilationRequest(hotSpotMethod, -1, 0L), false, compileOptions); 601 } 602 603 public Object invokeManagementAction(String actionName, Object[] params) throws Exception { 604 if ("dumpMethod".equals(actionName)) { 605 if (params.length != 0 && params[0] instanceof HotSpotResolvedJavaMethod) { 606 HotSpotResolvedJavaMethod method = param(params, 0, "method", HotSpotResolvedJavaMethod.class, null); 607 String filter = param(params, 1, "filter", String.class, ":3"); 608 String host = param(params, 2, "host", String.class, "localhost"); 609 Number port = param(params, 3, "port", Number.class, 4445); 610 dumpMethod(method, filter, host, port.intValue()); 611 } else { 612 String className = param(params, 0, "className", String.class, null); 613 String methodName = param(params, 1, "methodName", String.class, null); 614 String filter = param(params, 2, "filter", String.class, ":3"); 615 String host = param(params, 3, "host", String.class, "localhost"); 616 Number port = param(params, 4, "port", Number.class, 4445); 617 dumpMethod(className, methodName, filter, host, port.intValue()); 618 } 619 } 620 return null; 621 } 622 623 private static <T> T param(Object[] arr, int index, String name, Class<T> type, T defaultValue) { 624 Object value = arr.length > index ? arr[index] : null; 625 if (value == null || (value instanceof String && ((String) value).isEmpty())) { 626 if (defaultValue == null) { 627 throw new IllegalArgumentException(name + " must be specified"); 628 } 629 value = defaultValue; 630 } 631 if (type.isInstance(value)) { 632 return type.cast(value); 633 } 634 throw new IllegalArgumentException("Expecting " + type.getName() + " for " + name + " but was " + value); 635 } 636 }