comparison graal/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/CompilationTask.java @ 21780:3d15183f3c93

Introduce Compiler interface in jvmci. Use it from jvmci.hotspot.CompilationTask
author Gilles Duboscq <gilles.m.duboscq@oracle.com>
date Wed, 03 Jun 2015 15:47:54 +0200
parents graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java@77acf6ba2fc0
children 5b9adb645217
comparison
equal deleted inserted replaced
21779:20ace3139510 21780:3d15183f3c93
1 /*
2 * Copyright (c) 2012, 2015, 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.jvmci.hotspot;
24
25 import static com.oracle.jvmci.common.UnsafeAccess.*;
26 import static com.oracle.jvmci.debug.Debug.*;
27 import static com.oracle.jvmci.compiler.Compiler.*;
28
29 import java.lang.management.*;
30 import java.util.concurrent.*;
31
32 import com.oracle.jvmci.code.*;
33 import com.oracle.jvmci.compiler.Compiler;
34 import com.oracle.jvmci.debug.*;
35 import com.oracle.jvmci.debug.Debug.Scope;
36 import com.oracle.jvmci.debug.internal.*;
37 import com.oracle.jvmci.hotspot.events.*;
38 import com.oracle.jvmci.hotspot.events.EventProvider.CompilationEvent;
39 import com.oracle.jvmci.hotspot.events.EventProvider.CompilerFailureEvent;
40 import com.oracle.jvmci.meta.*;
41 import com.oracle.jvmci.service.*;
42
43 //JaCoCo Exclude
44
45 public class CompilationTask {
46
47 private static final DebugMetric BAILOUTS = Debug.metric("Bailouts");
48
49 private static final EventProvider eventProvider;
50 static {
51 EventProvider provider = Services.loadSingle(EventProvider.class, false);
52 if (provider == null) {
53 eventProvider = new EmptyEventProvider();
54 } else {
55 eventProvider = provider;
56 }
57 }
58 private static final Compiler compiler = Services.loadSingle(Compiler.class, true);
59
60 private final HotSpotResolvedJavaMethod method;
61 private final int entryBCI;
62 private final int id;
63
64 /**
65 * Specifies whether the compilation result is installed as the
66 * {@linkplain HotSpotNmethod#isDefault() default} nmethod for the compiled method.
67 */
68 private final boolean installAsDefault;
69
70 /**
71 * A {@link com.sun.management.ThreadMXBean} to be able to query some information about the
72 * current compiler thread, e.g. total allocated bytes.
73 */
74 private static final com.sun.management.ThreadMXBean threadMXBean = (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean();
75
76 /**
77 * The address of the GraalEnv associated with this compilation or 0L if no such object exists.
78 */
79 private final long graalEnv;
80
81 public CompilationTask(HotSpotResolvedJavaMethod method, int entryBCI, long graalEnv, int id, boolean installAsDefault) {
82 this.method = method;
83 this.entryBCI = entryBCI;
84 this.id = id;
85 this.graalEnv = graalEnv;
86 this.installAsDefault = installAsDefault;
87 }
88
89 public ResolvedJavaMethod getMethod() {
90 return method;
91 }
92
93 /**
94 * Returns the compilation id of this task.
95 *
96 * @return compile id
97 */
98 public int getId() {
99 return id;
100 }
101
102 public int getEntryBCI() {
103 return entryBCI;
104 }
105
106 /**
107 * Time spent in compilation.
108 */
109 private static final DebugTimer CompilationTime = Debug.timer("CompilationTime");
110
111 /**
112 * Meters the {@linkplain CompilationResult#getBytecodeSize() bytecodes} compiled.
113 */
114 private static final DebugMetric CompiledBytecodes = Debug.metric("CompiledBytecodes");
115
116 public static final DebugTimer CodeInstallationTime = Debug.timer("CodeInstallation");
117
118 public void runCompilation() {
119 HotSpotVMConfig config = HotSpotJVMCIRuntime.runtime().getConfig();
120 final long threadId = Thread.currentThread().getId();
121 long startCompilationTime = System.nanoTime();
122 HotSpotInstalledCode installedCode = null;
123 final boolean isOSR = entryBCI != Compiler.INVOCATION_ENTRY_BCI;
124
125 // Log a compilation event.
126 CompilationEvent compilationEvent = eventProvider.newCompilationEvent();
127
128 // If there is already compiled code for this method on our level we simply return.
129 // Graal compiles are always at the highest compile level, even in non-tiered mode so we
130 // only need to check for that value.
131 if (method.hasCodeAtLevel(entryBCI, config.compilationLevelFullOptimization)) {
132 return;
133 }
134
135 CompilationResult result = null;
136 try (DebugCloseable a = CompilationTime.start()) {
137 CompilationStatistics stats = CompilationStatistics.create(method, isOSR);
138 final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed();
139 if (printCompilation) {
140 TTY.println(getMethodDescription() + "...");
141 }
142
143 TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method);
144 final long start = System.currentTimeMillis();
145 final long allocatedBytesBefore = threadMXBean.getThreadAllocatedBytes(threadId);
146
147 try (Scope s = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true))) {
148 // Begin the compilation event.
149 compilationEvent.begin();
150
151 result = compiler.compile(method, entryBCI, mustRecordMethodInlining(config));
152
153 result.setId(getId());
154 } catch (Throwable e) {
155 throw Debug.handle(e);
156 } finally {
157 // End the compilation event.
158 compilationEvent.end();
159
160 filter.remove();
161 final boolean printAfterCompilation = PrintAfterCompilation.getValue() && !TTY.isSuppressed();
162
163 if (printAfterCompilation || printCompilation) {
164 final long stop = System.currentTimeMillis();
165 final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1;
166 final long allocatedBytesAfter = threadMXBean.getThreadAllocatedBytes(threadId);
167 final long allocatedBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024;
168
169 if (printAfterCompilation) {
170 TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dkB", stop - start, targetCodeSize, allocatedBytes));
171 } else if (printCompilation) {
172 TTY.println(String.format("%-6d Graal %-70s %-45s %-50s | %4dms %5dB %5dkB", id, "", "", "", stop - start, targetCodeSize, allocatedBytes));
173 }
174 }
175 }
176
177 try (DebugCloseable b = CodeInstallationTime.start()) {
178 installedCode = (HotSpotInstalledCode) installMethod(result);
179 }
180 stats.finish(method, installedCode);
181 } catch (BailoutException bailout) {
182 BAILOUTS.increment();
183 if (ExitVMOnBailout.getValue()) {
184 TTY.cachedOut.println(method.format("Bailout in %H.%n(%p)"));
185 bailout.printStackTrace(TTY.cachedOut);
186 System.exit(-1);
187 } else if (PrintBailout.getValue()) {
188 TTY.cachedOut.println(method.format("Bailout in %H.%n(%p)"));
189 bailout.printStackTrace(TTY.cachedOut);
190 }
191 } catch (Throwable t) {
192 if (PrintStackTraceOnException.getValue() || ExitVMOnException.getValue()) {
193 t.printStackTrace(TTY.cachedOut);
194 }
195
196 // Log a failure event.
197 CompilerFailureEvent event = eventProvider.newCompilerFailureEvent();
198 if (event.shouldWrite()) {
199 event.setCompileId(getId());
200 event.setMessage(t.getMessage());
201 event.commit();
202 }
203
204 if (ExitVMOnException.getValue()) {
205 System.exit(-1);
206 }
207 } finally {
208 int compiledBytecodes = 0;
209 int codeSize = 0;
210 if (result != null) {
211 compiledBytecodes = result.getBytecodeSize();
212 }
213 if (installedCode != null) {
214 codeSize = installedCode.getSize();
215 }
216 CompiledBytecodes.add(compiledBytecodes);
217
218 // Log a compilation event.
219 if (compilationEvent.shouldWrite()) {
220 compilationEvent.setMethod(method.format("%H.%n(%p)"));
221 compilationEvent.setCompileId(getId());
222 compilationEvent.setCompileLevel(config.compilationLevelFullOptimization);
223 compilationEvent.setSucceeded(result != null && installedCode != null);
224 compilationEvent.setIsOsr(isOSR);
225 compilationEvent.setCodeSize(codeSize);
226 compilationEvent.setInlinedBytes(compiledBytecodes);
227 compilationEvent.commit();
228 }
229
230 if (graalEnv != 0) {
231 long ctask = unsafe.getAddress(graalEnv + config.jvmciEnvTaskOffset);
232 assert ctask != 0L;
233 unsafe.putInt(ctask + config.compileTaskNumInlinedBytecodesOffset, compiledBytecodes);
234 }
235 long compilationTime = System.nanoTime() - startCompilationTime;
236 if ((config.ciTime || config.ciTimeEach) && installedCode != null) {
237 long timeUnitsPerSecond = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS);
238 CompilerToVM c2vm = HotSpotJVMCIRuntime.runtime().getCompilerToVM();
239 c2vm.notifyCompilationStatistics(id, method, entryBCI != Compiler.INVOCATION_ENTRY_BCI, compiledBytecodes, compilationTime, timeUnitsPerSecond, installedCode);
240 }
241 }
242 }
243
244 /**
245 * Determines whether to disable method inlining recording for the method being compiled.
246 */
247 private boolean mustRecordMethodInlining(HotSpotVMConfig config) {
248 if (config.ciTime || config.ciTimeEach || CompiledBytecodes.isEnabled()) {
249 return true;
250 }
251 if (graalEnv == 0 || unsafe.getByte(graalEnv + config.jvmciEnvJvmtiCanHotswapOrPostBreakpointOffset) != 0) {
252 return true;
253 }
254 return false;
255 }
256
257 private String getMethodDescription() {
258 return String.format("%-6d Graal %-70s %-45s %-50s %s", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature().toMethodDescriptor(),
259 entryBCI == Compiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + entryBCI + ") ");
260 }
261
262 private InstalledCode installMethod(final CompilationResult compResult) {
263 final HotSpotCodeCacheProvider codeCache = (HotSpotCodeCacheProvider) HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getCodeCache();
264 InstalledCode installedCode = null;
265 try (Scope s = Debug.scope("CodeInstall", new DebugDumpScope(String.valueOf(id), true), codeCache, method)) {
266 installedCode = codeCache.installMethod(method, compResult, graalEnv, installAsDefault);
267 } catch (Throwable e) {
268 throw Debug.handle(e);
269 }
270 return installedCode;
271 }
272
273 @Override
274 public String toString() {
275 return "Compilation[id=" + id + ", " + method.format("%H.%n(%p)") + (entryBCI == Compiler.INVOCATION_ENTRY_BCI ? "" : "@" + entryBCI) + "]";
276 }
277
278 /**
279 * Compiles a method to machine code.
280 */
281 public static void compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long graalEnv, int id) {
282 // Ensure a debug configuration for this thread is initialized
283 if (Debug.isEnabled() && DebugScope.getConfig() == null) {
284 DebugEnvironment.initialize(TTY.cachedOut);
285 }
286
287 CompilationTask task = new CompilationTask(method, entryBCI, graalEnv, id, true);
288 try (DebugConfigScope dcs = setConfig(new TopLevelDebugConfig())) {
289 task.runCompilation();
290 }
291 return;
292 }
293 }