1 /*
   2  * Copyright (c) 2011, 2012, 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 package com.oracle.graal.hotspot.bridge;
  25 
  26 import static com.oracle.graal.graph.UnsafeAccess.*;
  27 import static com.oracle.graal.hotspot.CompilationTask.*;
  28 import static com.oracle.graal.java.GraphBuilderPhase.*;
  29 import static com.oracle.graal.phases.common.InliningUtil.*;
  30 
  31 import java.io.*;
  32 import java.lang.reflect.*;
  33 import java.util.*;
  34 import java.util.concurrent.*;
  35 import java.util.concurrent.atomic.*;
  36 
  37 import com.oracle.graal.api.meta.*;
  38 import com.oracle.graal.debug.*;
  39 import com.oracle.graal.debug.internal.*;
  40 import com.oracle.graal.hotspot.*;
  41 import com.oracle.graal.hotspot.debug.*;
  42 import com.oracle.graal.hotspot.meta.*;
  43 import com.oracle.graal.hotspot.phases.*;
  44 import com.oracle.graal.java.*;
  45 import com.oracle.graal.nodes.*;
  46 import com.oracle.graal.nodes.debug.*;
  47 import com.oracle.graal.nodes.spi.*;
  48 import com.oracle.graal.phases.*;
  49 import com.oracle.graal.phases.PhasePlan.PhasePosition;
  50 import com.oracle.graal.printer.*;
  51 import com.oracle.graal.replacements.*;
  52 
  53 /**
  54  * Exits from the HotSpot VM into Java code.
  55  */
  56 public class VMToCompilerImpl implements VMToCompiler {
  57 
  58     private final HotSpotGraalRuntime graalRuntime;
  59 
  60     public final HotSpotResolvedPrimitiveType typeBoolean;
  61     public final HotSpotResolvedPrimitiveType typeChar;
  62     public final HotSpotResolvedPrimitiveType typeFloat;
  63     public final HotSpotResolvedPrimitiveType typeDouble;
  64     public final HotSpotResolvedPrimitiveType typeByte;
  65     public final HotSpotResolvedPrimitiveType typeShort;
  66     public final HotSpotResolvedPrimitiveType typeInt;
  67     public final HotSpotResolvedPrimitiveType typeLong;
  68     public final HotSpotResolvedPrimitiveType typeVoid;
  69 
  70     private ThreadPoolExecutor compileQueue;
  71     private ThreadPoolExecutor slowCompileQueue;
  72     private AtomicInteger compileTaskIds = new AtomicInteger();
  73 
  74     private volatile boolean bootstrapRunning;
  75 
  76     private PrintStream log = System.out;
  77 
  78     private boolean quietMeterAndTime;
  79 
  80     private long compilerStartTime;
  81 
  82     public VMToCompilerImpl(HotSpotGraalRuntime compiler) {
  83         this.graalRuntime = compiler;
  84 
  85         typeBoolean = new HotSpotResolvedPrimitiveType(Kind.Boolean);
  86         typeChar = new HotSpotResolvedPrimitiveType(Kind.Char);
  87         typeFloat = new HotSpotResolvedPrimitiveType(Kind.Float);
  88         typeDouble = new HotSpotResolvedPrimitiveType(Kind.Double);
  89         typeByte = new HotSpotResolvedPrimitiveType(Kind.Byte);
  90         typeShort = new HotSpotResolvedPrimitiveType(Kind.Short);
  91         typeInt = new HotSpotResolvedPrimitiveType(Kind.Int);
  92         typeLong = new HotSpotResolvedPrimitiveType(Kind.Long);
  93         typeVoid = new HotSpotResolvedPrimitiveType(Kind.Void);
  94     }
  95 
  96     private static void initMirror(HotSpotResolvedPrimitiveType type, long offset) {
  97         Class<?> mirror = type.mirror();
  98         unsafe.putObject(mirror, offset, type);
  99         assert unsafe.getObject(mirror, offset) == type;
 100     }
 101 
 102     public void startCompiler() throws Throwable {
 103 
 104         HotSpotVMConfig config = graalRuntime.getConfig();
 105         long offset = config.graalMirrorInClassOffset;
 106         initMirror(typeBoolean, offset);
 107         initMirror(typeChar, offset);
 108         initMirror(typeFloat, offset);
 109         initMirror(typeDouble, offset);
 110         initMirror(typeByte, offset);
 111         initMirror(typeShort, offset);
 112         initMirror(typeInt, offset);
 113         initMirror(typeLong, offset);
 114         initMirror(typeVoid, offset);
 115 
 116         if (GraalOptions.LogFile != null) {
 117             try {
 118                 final boolean enableAutoflush = true;
 119                 log = new PrintStream(new FileOutputStream(GraalOptions.LogFile), enableAutoflush);
 120             } catch (FileNotFoundException e) {
 121                 throw new RuntimeException("couldn't open log file: " + GraalOptions.LogFile, e);
 122             }
 123         }
 124 
 125         TTY.initialize(log);
 126 
 127         if (GraalOptions.Log == null && GraalOptions.Meter == null && GraalOptions.Time == null && GraalOptions.Dump == null) {
 128             if (GraalOptions.MethodFilter != null) {
 129                 TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time and Dump options are all null");
 130             }
 131         }
 132 
 133         if (config.ciTime) {
 134             quietMeterAndTime = (GraalOptions.Meter == null && GraalOptions.Time == null);
 135             GraalOptions.Debug = true;
 136             GraalOptions.Meter = "";
 137             GraalOptions.Time = "";
 138         }
 139 
 140         if (GraalOptions.Debug) {
 141             Debug.enable();
 142             if (GraalOptions.DebugReplacements) {
 143                 DebugEnvironment.initialize(log);
 144             }
 145         }
 146 
 147         // Install intrinsics.
 148         final HotSpotRuntime runtime = graalRuntime.getCapability(HotSpotRuntime.class);
 149         final Replacements replacements = graalRuntime.getCapability(Replacements.class);
 150         if (GraalOptions.Intrinsify) {
 151             Debug.scope("RegisterReplacements", new Object[]{new DebugDumpScope("RegisterReplacements")}, new Runnable() {
 152 
 153                 @Override
 154                 public void run() {
 155                     ServiceLoader<ReplacementsProvider> serviceLoader = ServiceLoader.loadInstalled(ReplacementsProvider.class);
 156                     for (ReplacementsProvider provider : serviceLoader) {
 157                         provider.registerReplacements(replacements);
 158                     }
 159                     runtime.registerReplacements(replacements);
 160                     if (GraalOptions.BootstrapReplacements) {
 161                         for (ResolvedJavaMethod method : replacements.getAllReplacements()) {
 162                             replacements.getMacroSubstitution(method);
 163                             replacements.getMethodSubstitution(method);
 164                             replacements.getSnippet(method);
 165                         }
 166                     }
 167                 }
 168             });
 169 
 170         }
 171 
 172         if (GraalOptions.DebugReplacements) {
 173             phaseTransition("replacements");
 174         }
 175 
 176         // Create compilation queue.
 177         BlockingQueue<Runnable> queue = GraalOptions.PriorityCompileQueue ? new PriorityBlockingQueue<Runnable>() : new LinkedBlockingQueue<Runnable>();
 178         compileQueue = new ThreadPoolExecutor(GraalOptions.Threads, GraalOptions.Threads, 0L, TimeUnit.MILLISECONDS, queue, CompilerThread.FACTORY);
 179 
 180         if (GraalOptions.SlowCompileThreads) {
 181             BlockingQueue<Runnable> slowQueue = GraalOptions.PriorityCompileQueue ? new PriorityBlockingQueue<Runnable>() : new LinkedBlockingQueue<Runnable>();
 182             slowCompileQueue = new ThreadPoolExecutor(GraalOptions.Threads, GraalOptions.Threads, 0L, TimeUnit.MILLISECONDS, slowQueue, CompilerThread.LOW_PRIORITY_FACTORY);
 183         }
 184 
 185         // Create queue status printing thread.
 186         if (GraalOptions.PrintQueue) {
 187             Thread t = new Thread() {
 188 
 189                 @Override
 190                 public void run() {
 191                     while (true) {
 192                         if (slowCompileQueue == null) {
 193                             TTY.println(compileQueue.toString());
 194                         } else {
 195                             TTY.println("fast: " + compileQueue.toString() + " slow: " + slowCompileQueue);
 196                         }
 197                         try {
 198                             Thread.sleep(1000);
 199                         } catch (InterruptedException e) {
 200                         }
 201                     }
 202                 }
 203             };
 204             t.setDaemon(true);
 205             t.start();
 206         }
 207 
 208         if (GraalOptions.BenchmarkDynamicCounters) {
 209             System.setErr(new PrintStream(new BenchmarkCountersOutputStream(System.err, " starting =====", " PASSED in ", "\n")));
 210             System.setOut(new PrintStream(new BenchmarkCountersOutputStream(System.out, "Iteration ~ (~s) begins: ", "Iteration ~ (~s) ends:   ", "\n")));
 211             DynamicCounterNode.excludedClassPrefix = "Lcom/oracle/graal/";
 212             DynamicCounterNode.enabled = true;
 213         }
 214         if (GraalOptions.GenericDynamicCounters) {
 215             DynamicCounterNode.enabled = true;
 216         }
 217         compilerStartTime = System.nanoTime();
 218     }
 219 
 220     private final class BenchmarkCountersOutputStream extends CallbackOutputStream {
 221 
 222         private long startTime;
 223         private boolean waitingForEnd;
 224 
 225         private BenchmarkCountersOutputStream(PrintStream delegate, String... patterns) {
 226             super(delegate, patterns);
 227         }
 228 
 229         @Override
 230         protected void patternFound(int index) {
 231             switch (index) {
 232                 case 0:
 233                     startTime = System.nanoTime();
 234                     DynamicCounterNode.clear();
 235                     break;
 236                 case 1:
 237                     waitingForEnd = true;
 238                     break;
 239                 case 2:
 240                     if (waitingForEnd) {
 241                         waitingForEnd = false;
 242                         DynamicCounterNode.dump(delegate, (System.nanoTime() - startTime) / 1000000000d);
 243                     }
 244                     break;
 245             }
 246         }
 247     }
 248 
 249     public abstract static class CallbackOutputStream extends OutputStream {
 250 
 251         protected final PrintStream delegate;
 252         private final byte[][] patterns;
 253         private final int[] positions;
 254 
 255         public CallbackOutputStream(PrintStream delegate, String... patterns) {
 256             this.delegate = delegate;
 257             this.positions = new int[patterns.length];
 258             this.patterns = new byte[patterns.length][];
 259             for (int i = 0; i < patterns.length; i++) {
 260                 this.patterns[i] = patterns[i].getBytes();
 261             }
 262         }
 263 
 264         protected abstract void patternFound(int index);
 265 
 266         @Override
 267         public void write(int b) throws IOException {
 268             try {
 269                 delegate.write(b);
 270                 for (int i = 0; i < patterns.length; i++) {
 271                     int j = positions[i];
 272                     byte[] cs = patterns[i];
 273                     byte patternChar = cs[j];
 274                     if (patternChar == '~' && Character.isDigit(b)) {
 275                         // nothing to do...
 276                     } else {
 277                         if (patternChar == '~') {
 278                             patternChar = cs[++positions[i]];
 279                         }
 280                         if (b == patternChar) {
 281                             positions[i]++;
 282                         } else {
 283                             positions[i] = 0;
 284                         }
 285                     }
 286                     if (positions[i] == patterns[i].length) {
 287                         positions[i] = 0;
 288                         patternFound(i);
 289                     }
 290                 }
 291             } catch (RuntimeException e) {
 292                 e.printStackTrace(delegate);
 293                 throw e;
 294             }
 295         }
 296     }
 297 
 298     /**
 299      * Take action related to entering a new execution phase.
 300      * 
 301      * @param phase the execution phase being entered
 302      */
 303     protected void phaseTransition(String phase) {
 304         CompilationStatistics.clear(phase);
 305         if (graalRuntime.getConfig().ciTime) {
 306             parsedBytecodesPerSecond = MetricRateInPhase.snapshot(phase, parsedBytecodesPerSecond, BytecodesParsed, CompilationTime, TimeUnit.SECONDS);
 307             inlinedBytecodesPerSecond = MetricRateInPhase.snapshot(phase, inlinedBytecodesPerSecond, InlinedBytecodes, CompilationTime, TimeUnit.SECONDS);
 308         }
 309     }
 310 
 311     /**
 312      * This method is the first method compiled during bootstrapping. Put any code in there that
 313      * warms up compiler paths that are otherwise not exercised during bootstrapping and lead to
 314      * later deoptimization when application code is compiled.
 315      */
 316     @SuppressWarnings("unused")
 317     @Deprecated
 318     private synchronized void compileWarmup() {
 319         // Method is synchronized to exercise the synchronization code in the compiler.
 320     }
 321 
 322     public void bootstrap() throws Throwable {
 323         TTY.print("Bootstrapping Graal");
 324         TTY.flush();
 325         long startTime = System.currentTimeMillis();
 326 
 327         bootstrapRunning = true;
 328         boolean firstRun = true;
 329         do {
 330             // Initialize compile queue with a selected set of methods.
 331             Class<Object> objectKlass = Object.class;
 332             if (firstRun) {
 333                 enqueue(getClass().getDeclaredMethod("compileWarmup"));
 334                 enqueue(objectKlass.getDeclaredMethod("equals", Object.class));
 335                 enqueue(objectKlass.getDeclaredMethod("toString"));
 336                 firstRun = false;
 337             } else {
 338                 for (int i = 0; i < 100; i++) {
 339                     enqueue(getClass().getDeclaredMethod("bootstrap"));
 340                 }
 341             }
 342 
 343             // Compile until the queue is empty.
 344             int z = 0;
 345             while (true) {
 346                 try {
 347                     assert !CompilationTask.withinEnqueue.get();
 348                     CompilationTask.withinEnqueue.set(Boolean.TRUE);
 349                     if (slowCompileQueue == null) {
 350                         if (compileQueue.getCompletedTaskCount() >= Math.max(3, compileQueue.getTaskCount())) {
 351                             break;
 352                         }
 353                     } else {
 354                         if (compileQueue.getCompletedTaskCount() + slowCompileQueue.getCompletedTaskCount() >= Math.max(3, compileQueue.getTaskCount() + slowCompileQueue.getTaskCount())) {
 355                             break;
 356                         }
 357                     }
 358                 } finally {
 359                     CompilationTask.withinEnqueue.set(Boolean.FALSE);
 360                 }
 361 
 362                 Thread.sleep(100);
 363                 while (z < compileQueue.getCompletedTaskCount() / 100) {
 364                     ++z;
 365                     TTY.print(".");
 366                     TTY.flush();
 367                 }
 368             }
 369         } while ((System.currentTimeMillis() - startTime) <= GraalOptions.TimedBootstrap);
 370 
 371         phaseTransition("bootstrap");
 372 
 373         bootstrapRunning = false;
 374 
 375         TTY.println(" in %d ms", System.currentTimeMillis() - startTime);
 376         if (graalRuntime.getCache() != null) {
 377             graalRuntime.getCache().clear();
 378         }
 379         System.gc();
 380         phaseTransition("bootstrap2");
 381 
 382     }
 383 
 384     private MetricRateInPhase parsedBytecodesPerSecond;
 385     private MetricRateInPhase inlinedBytecodesPerSecond;
 386 
 387     private void enqueue(Method m) throws Throwable {
 388         JavaMethod javaMethod = graalRuntime.getRuntime().lookupJavaMethod(m);
 389         assert !Modifier.isAbstract(((HotSpotResolvedJavaMethod) javaMethod).getModifiers()) && !Modifier.isNative(((HotSpotResolvedJavaMethod) javaMethod).getModifiers()) : javaMethod;
 390         compileMethod((HotSpotResolvedJavaMethod) javaMethod, StructuredGraph.INVOCATION_ENTRY_BCI, false, 10);
 391     }
 392 
 393     private static void shutdownCompileQueue(ThreadPoolExecutor queue) throws InterruptedException {
 394         if (queue != null) {
 395             queue.shutdown();
 396             if (Debug.isEnabled() && GraalOptions.Dump != null) {
 397                 // Wait 2 seconds to flush out all graph dumps that may be of interest
 398                 queue.awaitTermination(2, TimeUnit.SECONDS);
 399             }
 400         }
 401     }
 402 
 403     public void shutdownCompiler() throws Throwable {
 404         try {
 405             assert !CompilationTask.withinEnqueue.get();
 406             CompilationTask.withinEnqueue.set(Boolean.TRUE);
 407             shutdownCompileQueue(compileQueue);
 408             shutdownCompileQueue(slowCompileQueue);
 409         } finally {
 410             CompilationTask.withinEnqueue.set(Boolean.FALSE);
 411         }
 412 
 413         if (Debug.isEnabled() && !quietMeterAndTime) {
 414             List<DebugValueMap> topLevelMaps = DebugValueMap.getTopLevelMaps();
 415             List<DebugValue> debugValues = KeyRegistry.getDebugValues();
 416             if (debugValues.size() > 0) {
 417                 ArrayList<DebugValue> sortedValues = new ArrayList<>(debugValues);
 418                 Collections.sort(sortedValues);
 419 
 420                 if (GraalOptions.SummarizeDebugValues) {
 421                     printSummary(topLevelMaps, sortedValues);
 422                 } else if (GraalOptions.PerThreadDebugValues) {
 423                     for (DebugValueMap map : topLevelMaps) {
 424                         TTY.println("Showing the results for thread: " + map.getName());
 425                         map.group();
 426                         map.normalize();
 427                         printMap(map, sortedValues, 0);
 428                     }
 429                 } else {
 430                     DebugValueMap globalMap = new DebugValueMap("Global");
 431                     for (DebugValueMap map : topLevelMaps) {
 432                         if (GraalOptions.SummarizePerPhase) {
 433                             flattenChildren(map, globalMap);
 434                         } else {
 435                             globalMap.addChild(map);
 436                         }
 437                     }
 438                     if (!GraalOptions.SummarizePerPhase) {
 439                         globalMap.group();
 440                     }
 441                     globalMap.normalize();
 442                     printMap(globalMap, sortedValues, 0);
 443                 }
 444             }
 445         }
 446         phaseTransition("final");
 447 
 448         if (graalRuntime.getConfig().ciTime) {
 449             parsedBytecodesPerSecond.printAll("ParsedBytecodesPerSecond", System.out);
 450             inlinedBytecodesPerSecond.printAll("InlinedBytecodesPerSecond", System.out);
 451         }
 452 
 453         SnippetCounter.printGroups(TTY.out().out());
 454         if (GraalOptions.GenericDynamicCounters) {
 455             DynamicCounterNode.dump(System.out, (System.nanoTime() - compilerStartTime) / 1000000000d);
 456         }
 457     }
 458 
 459     private void flattenChildren(DebugValueMap map, DebugValueMap globalMap) {
 460         globalMap.addChild(map);
 461         for (DebugValueMap child : map.getChildren()) {
 462             flattenChildren(child, globalMap);
 463         }
 464         map.clearChildren();
 465     }
 466 
 467     private static void printSummary(List<DebugValueMap> topLevelMaps, List<DebugValue> debugValues) {
 468         DebugValueMap result = new DebugValueMap("Summary");
 469         for (int i = debugValues.size() - 1; i >= 0; i--) {
 470             DebugValue debugValue = debugValues.get(i);
 471             int index = debugValue.getIndex();
 472             long total = collectTotal(topLevelMaps, index);
 473             result.setCurrentValue(index, total);
 474         }
 475         printMap(result, debugValues, 0);
 476     }
 477 
 478     static long collectTotal(DebugValue value) {
 479         List<DebugValueMap> maps = DebugValueMap.getTopLevelMaps();
 480         long total = 0;
 481         for (int i = 0; i < maps.size(); i++) {
 482             DebugValueMap map = maps.get(i);
 483             int index = value.getIndex();
 484             total += map.getCurrentValue(index);
 485             total += collectTotal(map.getChildren(), index);
 486         }
 487         return total;
 488     }
 489 
 490     private static long collectTotal(List<DebugValueMap> maps, int index) {
 491         long total = 0;
 492         for (int i = 0; i < maps.size(); i++) {
 493             DebugValueMap map = maps.get(i);
 494             total += map.getCurrentValue(index);
 495             total += collectTotal(map.getChildren(), index);
 496         }
 497         return total;
 498     }
 499 
 500     private static void printMap(DebugValueMap map, List<DebugValue> debugValues, int level) {
 501 
 502         printIndent(level);
 503         TTY.println("%s", map.getName());
 504 
 505         for (DebugValue value : debugValues) {
 506             long l = map.getCurrentValue(value.getIndex());
 507             if (l != 0) {
 508                 printIndent(level + 1);
 509                 TTY.println(value.getName() + "=" + value.toString(l));
 510             }
 511         }
 512 
 513         for (DebugValueMap child : map.getChildren()) {
 514             printMap(child, debugValues, level + 1);
 515         }
 516     }
 517 
 518     private static void printIndent(int level) {
 519         for (int i = 0; i < level; ++i) {
 520             TTY.print("    ");
 521         }
 522         TTY.print("|-> ");
 523     }
 524 
 525     @Override
 526     public boolean compileMethod(long metaspaceMethod, final HotSpotResolvedObjectType holder, final int entryBCI, boolean blocking, int priority) throws Throwable {
 527         HotSpotResolvedJavaMethod method = holder.createMethod(metaspaceMethod);
 528         return compileMethod(method, entryBCI, blocking, priority);
 529     }
 530 
 531     /**
 532      * Compiles a method to machine code.
 533      * 
 534      * @return true if the method is in the queue (either added to the queue or already in the
 535      *         queue)
 536      */
 537     public boolean compileMethod(final HotSpotResolvedJavaMethod method, final int entryBCI, boolean blocking, int priority) throws Throwable {
 538         CompilationTask current = method.currentTask();
 539         boolean osrCompilation = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI;
 540         if (osrCompilation && bootstrapRunning) {
 541             // no OSR compilations during bootstrap - the compiler is just too slow at this point,
 542             // and we know that there are no endless loops
 543             return current != null && (current.isInProgress() || !current.isCancelled());
 544         }
 545 
 546         if (CompilationTask.withinEnqueue.get()) {
 547             // This is required to avoid deadlocking a compiler thread. The issue is that a
 548             // java.util.concurrent.BlockingQueue is used to implement the compilation worker
 549             // queues. If a compiler thread triggers a compilation, then it may be blocked trying
 550             // to add something to its own queue.
 551             return current != null && (current.isInProgress() || !current.isCancelled());
 552         }
 553         CompilationTask.withinEnqueue.set(Boolean.TRUE);
 554 
 555         try {
 556             if (!blocking && current != null) {
 557                 if (current.isInProgress()) {
 558                     if (current.getEntryBCI() == entryBCI) {
 559                         // a compilation with the correct bci is already in progress, so just return
 560                         // true
 561                         return true;
 562                     }
 563                 } else {
 564                     if (GraalOptions.PriorityCompileQueue) {
 565                         // normally compilation tasks will only be re-queued when they get a
 566                         // priority boost, so cancel the old task and add a new one
 567                         current.cancel();
 568                     } else if (!current.isCancelled()) {
 569                         // without a prioritizing compile queue it makes no sense to re-queue the
 570                         // compilation task
 571                         return true;
 572                     }
 573                 }
 574             }
 575 
 576             final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(method);
 577             int id = compileTaskIds.incrementAndGet();
 578             // OSR compilations need to be finished quickly, so they get max priority
 579             int queuePriority = osrCompilation ? -1 : priority;
 580             CompilationTask task = CompilationTask.create(graalRuntime, createPhasePlan(optimisticOpts, osrCompilation), optimisticOpts, method, entryBCI, id, queuePriority);
 581             if (blocking) {
 582                 task.runCompilation();
 583                 return false;
 584             } else {
 585                 try {
 586                     method.setCurrentTask(task);
 587                     if (GraalOptions.SlowCompileThreads && priority > GraalOptions.SlowQueueCutoff) {
 588                         slowCompileQueue.execute(task);
 589                     } else {
 590                         compileQueue.execute(task);
 591                     }
 592                     return true;
 593                 } catch (RejectedExecutionException e) {
 594                     // The compile queue was already shut down.
 595                     return false;
 596                 }
 597             }
 598         } finally {
 599             CompilationTask.withinEnqueue.set(Boolean.FALSE);
 600         }
 601     }
 602 
 603     @Override
 604     public JavaMethod createUnresolvedJavaMethod(String name, String signature, JavaType holder) {
 605         return new HotSpotMethodUnresolved(name, signature, holder);
 606     }
 607 
 608     @Override
 609     public JavaField createJavaField(JavaType holder, String name, JavaType type, int offset, int flags, boolean internal) {
 610         if (offset != -1) {
 611             HotSpotResolvedObjectType resolved = (HotSpotResolvedObjectType) holder;
 612             return resolved.createField(name, type, offset, flags, internal);
 613         }
 614         return new HotSpotUnresolvedField(holder, name, type);
 615     }
 616 
 617     @Override
 618     public ResolvedJavaMethod createResolvedJavaMethod(JavaType holder, long metaspaceMethod) {
 619         HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) holder;
 620         return type.createMethod(metaspaceMethod);
 621     }
 622 
 623     @Override
 624     public ResolvedJavaType createPrimitiveJavaType(int basicType) {
 625         switch (basicType) {
 626             case 4:
 627                 return typeBoolean;
 628             case 5:
 629                 return typeChar;
 630             case 6:
 631                 return typeFloat;
 632             case 7:
 633                 return typeDouble;
 634             case 8:
 635                 return typeByte;
 636             case 9:
 637                 return typeShort;
 638             case 10:
 639                 return typeInt;
 640             case 11:
 641                 return typeLong;
 642             case 14:
 643                 return typeVoid;
 644             default:
 645                 throw new IllegalArgumentException("Unknown basic type: " + basicType);
 646         }
 647     }
 648 
 649     @Override
 650     public HotSpotUnresolvedJavaType createUnresolvedJavaType(String name) {
 651         int dims = 0;
 652         int startIndex = 0;
 653         while (name.charAt(startIndex) == '[') {
 654             startIndex++;
 655             dims++;
 656         }
 657 
 658         // Decode name if necessary.
 659         if (name.charAt(name.length() - 1) == ';') {
 660             assert name.charAt(startIndex) == 'L';
 661             return new HotSpotUnresolvedJavaType(name, name.substring(startIndex + 1, name.length() - 1), dims);
 662         } else {
 663             return new HotSpotUnresolvedJavaType(HotSpotUnresolvedJavaType.getFullName(name, dims), name, dims);
 664         }
 665     }
 666 
 667     @Override
 668     public HotSpotResolvedObjectType createResolvedJavaType(long metaspaceKlass, String name, String simpleName, Class javaMirror, boolean hasFinalizableSubclass, int sizeOrSpecies) {
 669         HotSpotResolvedObjectType type = new HotSpotResolvedObjectType(metaspaceKlass, name, simpleName, javaMirror, hasFinalizableSubclass, sizeOrSpecies);
 670 
 671         long offset = HotSpotGraalRuntime.getInstance().getConfig().graalMirrorInClassOffset;
 672         if (!unsafe.compareAndSwapObject(javaMirror, offset, null, type)) {
 673             // lost the race - return the existing value instead
 674             type = (HotSpotResolvedObjectType) unsafe.getObject(javaMirror, offset);
 675         }
 676         return type;
 677     }
 678 
 679     @Override
 680     public Constant createConstant(Kind kind, long value) {
 681         if (kind == Kind.Long) {
 682             return Constant.forLong(value);
 683         } else if (kind == Kind.Int) {
 684             return Constant.forInt((int) value);
 685         } else if (kind == Kind.Short) {
 686             return Constant.forShort((short) value);
 687         } else if (kind == Kind.Char) {
 688             return Constant.forChar((char) value);
 689         } else if (kind == Kind.Byte) {
 690             return Constant.forByte((byte) value);
 691         } else if (kind == Kind.Boolean) {
 692             return (value == 0) ? Constant.FALSE : Constant.TRUE;
 693         } else {
 694             throw new IllegalArgumentException();
 695         }
 696     }
 697 
 698     @Override
 699     public Constant createConstantFloat(float value) {
 700         return Constant.forFloat(value);
 701     }
 702 
 703     @Override
 704     public Constant createConstantDouble(double value) {
 705         return Constant.forDouble(value);
 706     }
 707 
 708     @Override
 709     public Constant createConstantObject(Object object) {
 710         return Constant.forObject(object);
 711     }
 712 
 713     @Override
 714     public LocalImpl createLocalImpl(String name, String type, HotSpotResolvedObjectType holder, int bciStart, int bciEnd, int slot) {
 715         return new LocalImpl(name, type, holder, bciStart, bciEnd, slot);
 716     }
 717 
 718     public PhasePlan createPhasePlan(OptimisticOptimizations optimisticOpts, boolean onStackReplacement) {
 719         PhasePlan phasePlan = new PhasePlan();
 720         phasePlan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(graalRuntime.getRuntime(), GraphBuilderConfiguration.getDefault(), optimisticOpts));
 721         if (onStackReplacement) {
 722             phasePlan.addPhase(PhasePosition.AFTER_PARSING, new OnStackReplacementPhase());
 723         }
 724         phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase());
 725         return phasePlan;
 726     }
 727 
 728     @Override
 729     public PrintStream log() {
 730         return log;
 731     }
 732 }