1 /* 2 * Copyright (c) 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 package com.oracle.graal.hotspot; 24 25 import static com.oracle.graal.nodes.StructuredGraph.*; 26 import static com.oracle.graal.phases.common.InliningUtil.*; 27 28 import java.lang.reflect.Modifier; 29 import java.util.concurrent.*; 30 31 import com.oracle.graal.api.code.*; 32 import com.oracle.graal.api.meta.*; 33 import com.oracle.graal.compiler.*; 34 import com.oracle.graal.debug.*; 35 import com.oracle.graal.debug.internal.*; 36 import com.oracle.graal.hotspot.meta.*; 37 import com.oracle.graal.nodes.*; 38 import com.oracle.graal.nodes.spi.*; 39 import com.oracle.graal.phases.*; 40 41 public final class CompilationTask implements Runnable, Comparable<CompilationTask> { 42 43 public static final ThreadLocal<Boolean> withinEnqueue = new ThreadLocal<Boolean>() { 44 45 @Override 46 protected Boolean initialValue() { 47 return Boolean.valueOf(Thread.currentThread() instanceof CompilerThread); 48 } 49 }; 50 51 private volatile boolean cancelled; 52 private volatile boolean inProgress; 53 54 private final HotSpotGraalRuntime graalRuntime; 55 private final PhasePlan plan; 56 private final OptimisticOptimizations optimisticOpts; 57 private final HotSpotResolvedJavaMethod method; 58 private final int entryBCI; 59 private final int id; 60 private final int priority; 61 62 public static CompilationTask create(HotSpotGraalRuntime graalRuntime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int entryBCI, int id, int priority) { 63 return new CompilationTask(graalRuntime, plan, optimisticOpts, method, entryBCI, id, priority); 64 } 65 66 private CompilationTask(HotSpotGraalRuntime graalRuntime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int entryBCI, int id, int priority) { 67 this.graalRuntime = graalRuntime; 68 this.plan = plan; 69 this.method = method; 70 this.optimisticOpts = optimisticOpts; 71 this.entryBCI = entryBCI; 72 this.id = id; 73 this.priority = priority; 74 } 75 76 public ResolvedJavaMethod getMethod() { 77 return method; 78 } 79 80 public int getPriority() { 81 return priority; 82 } 83 84 public void cancel() { 85 cancelled = true; 86 } 87 88 public boolean isInProgress() { 89 return inProgress; 90 } 91 92 public boolean isCancelled() { 93 return cancelled; 94 } 95 96 public int getEntryBCI() { 97 return entryBCI; 98 } 99 100 public void run() { 101 withinEnqueue.set(Boolean.FALSE); 102 try { 103 if (cancelled) { 104 return; 105 } 106 inProgress = true; 107 if (GraalOptions.DynamicCompilePriority) { 108 int threadPriority = priority < GraalOptions.SlowQueueCutoff ? Thread.NORM_PRIORITY : Thread.MIN_PRIORITY; 109 if (Thread.currentThread().getPriority() != threadPriority) { 110 Thread.currentThread().setPriority(threadPriority); 111 } 112 } 113 runCompilation(); 114 } finally { 115 if (method.currentTask() == this) { 116 method.setCurrentTask(null); 117 } 118 graalRuntime.getCompilerToVM().clearQueuedForCompilation(method); 119 inProgress = false; 120 withinEnqueue.set(Boolean.TRUE); 121 } 122 } 123 124 /** 125 * Time spent in compilation. 126 */ 127 public static final DebugTimer CompilationTime = Debug.timer("CompilationTime"); 128 129 public void runCompilation() { 130 CompilationStatistics stats = CompilationStatistics.create(method, entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI); 131 try (TimerCloseable a = CompilationTime.start()) { 132 final boolean printCompilation = GraalOptions.PrintCompilation && !TTY.isSuppressed(); 133 if (printCompilation) { 134 TTY.println(String.format("%-6d Graal %-70s %-45s %-50s %s...", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature(), 135 entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + entryBCI + ") ")); 136 } 137 if (GraalOptions.HotSpotPrintCompilation) { 138 printCompilation(); 139 } 140 141 CompilationResult result = null; 142 TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method); 143 long start = System.currentTimeMillis(); 144 try { 145 result = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true), new Callable<CompilationResult>() { 146 147 @Override 148 public CompilationResult call() throws Exception { 149 graalRuntime.evictDeoptedGraphs(); 150 Replacements replacements = graalRuntime.getReplacements(); 151 StructuredGraph graph = replacements.getMethodSubstitution(method); 152 if (graph == null || entryBCI != INVOCATION_ENTRY_BCI) { 153 graph = new StructuredGraph(method, entryBCI); 154 } else { 155 // Compiling method substitution - must clone the graph 156 graph = graph.copy(); 157 } 158 InlinedBytecodes.add(method.getCodeSize()); 159 return GraalCompiler.compileMethod(graalRuntime.getRuntime(), replacements, graalRuntime.getBackend(), graalRuntime.getTarget(), method, graph, graalRuntime.getCache(), plan, 160 optimisticOpts, method.getSpeculationLog()); 161 } 162 }); 163 } finally { 164 filter.remove(); 165 if (printCompilation) { 166 TTY.println(String.format("%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, (result != null ? result.getTargetCodeSize() : -1))); 167 } 168 } 169 170 installMethod(result); 171 } catch (BailoutException bailout) { 172 Debug.metric("Bailouts").increment(); 173 if (GraalOptions.ExitVMOnBailout) { 174 TTY.cachedOut.println(MetaUtil.format("Bailout in %H.%n(%p)", method)); 175 bailout.printStackTrace(TTY.cachedOut); 176 System.exit(-1); 177 } else if (GraalOptions.PrintBailout) { 178 TTY.cachedOut.println(MetaUtil.format("Bailout in %H.%n(%p)", method)); 179 bailout.printStackTrace(TTY.cachedOut); 180 } 181 } catch (Throwable t) { 182 if (GraalOptions.ExitVMOnException) { 183 t.printStackTrace(TTY.cachedOut); 184 System.exit(-1); 185 } 186 } 187 stats.finish(method); 188 } 189 190 /** 191 * Print a HotSpot-style compilation message to the console. 192 */ 193 private void printCompilation() { 194 final boolean isOSR = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI; 195 final int mod = method.getModifiers(); 196 TTY.println(String.format("%7d %4d %c%c%c%c%c %s %s(%d bytes)", 197 0, id, 198 isOSR ? '%' : ' ', 199 Modifier.isSynchronized(mod) ? 's' : ' ', 200 ' ', 201 ' ', 202 Modifier.isNative(mod) ? 'n' : ' ', 203 MetaUtil.format("%H::%n(%p)", method), 204 isOSR ? "@ " + entryBCI + " " : "", method.getCodeSize())); 205 } 206 207 private void installMethod(final CompilationResult compResult) { 208 Debug.scope("CodeInstall", new Object[]{new DebugDumpScope(String.valueOf(id), true), graalRuntime.getRuntime(), method}, new Runnable() { 209 210 @Override 211 public void run() { 212 HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, entryBCI, compResult); 213 if (Debug.isDumpEnabled()) { 214 Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); 215 } 216 } 217 218 }); 219 } 220 221 @Override 222 public int compareTo(CompilationTask o) { 223 if (priority < o.priority) { 224 return -1; 225 } 226 if (priority > o.priority) { 227 return 1; 228 } 229 return id < o.id ? -1 : (id > o.id ? 1 : 0); 230 } 231 232 @Override 233 public String toString() { 234 return "Compilation[id=" + id + ", prio=" + priority + " " + MetaUtil.format("%H.%n(%p)", method) + (entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "@" + entryBCI) + "]"; 235 } 236 }