comparison graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/jvmci/HotSpotCodeCacheProvider.java @ 21526:1da7aef31a08

created com.oracle.graal.hotspot.jvmci package and moved classes destined for future JVMCI module into it (JBS:GRAAL-53)
author Doug Simon <doug.simon@oracle.com>
date Tue, 19 May 2015 23:16:07 +0200
parents graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java@b04f579c803f
children
comparison
equal deleted inserted replaced
21489:b3f1d8b23037 21526:1da7aef31a08
1 /*
2 * Copyright (c) 2013, 2014, 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.jvmci;
24
25 import static com.oracle.graal.hotspot.jvmci.HotSpotCompressedNullConstant.*;
26
27 import java.lang.reflect.*;
28 import java.util.*;
29
30 import com.oracle.graal.api.code.*;
31 import com.oracle.graal.api.code.CodeUtil.DefaultRefMapFormatter;
32 import com.oracle.graal.api.code.CodeUtil.RefMapFormatter;
33 import com.oracle.graal.api.code.CompilationResult.Call;
34 import com.oracle.graal.api.code.CompilationResult.ConstantReference;
35 import com.oracle.graal.api.code.CompilationResult.DataPatch;
36 import com.oracle.graal.api.code.CompilationResult.Infopoint;
37 import com.oracle.graal.api.code.CompilationResult.Mark;
38 import com.oracle.graal.api.code.DataSection.Data;
39 import com.oracle.graal.api.code.DataSection.DataBuilder;
40 import com.oracle.graal.api.meta.*;
41 import com.oracle.graal.compiler.common.*;
42 import com.oracle.graal.debug.*;
43 import com.oracle.graal.hotspot.*;
44 import com.oracle.graal.hotspot.meta.*;
45 import com.oracle.graal.printer.*;
46
47 /**
48 * HotSpot implementation of {@link CodeCacheProvider}.
49 */
50 public class HotSpotCodeCacheProvider implements CodeCacheProvider {
51
52 protected final HotSpotGraalRuntimeProvider runtime;
53 public final HotSpotVMConfig config;
54 protected final TargetDescription target;
55 protected final RegisterConfig regConfig;
56
57 public HotSpotCodeCacheProvider(HotSpotGraalRuntimeProvider runtime, HotSpotVMConfig config, TargetDescription target, RegisterConfig regConfig) {
58 this.runtime = runtime;
59 this.config = config;
60 this.target = target;
61 this.regConfig = regConfig;
62 }
63
64 @Override
65 public String disassemble(CompilationResult compResult, InstalledCode installedCode) {
66 byte[] code = installedCode == null ? Arrays.copyOf(compResult.getTargetCode(), compResult.getTargetCodeSize()) : installedCode.getCode();
67 if (code == null) {
68 // Method was deoptimized/invalidated
69 return "";
70 }
71 long start = installedCode == null ? 0L : installedCode.getStart();
72 HexCodeFile hcf = new HexCodeFile(code, start, target.arch.getName(), target.wordSize * 8);
73 if (compResult != null) {
74 HexCodeFile.addAnnotations(hcf, compResult.getAnnotations());
75 addExceptionHandlersComment(compResult, hcf);
76 Register fp = regConfig.getFrameRegister();
77 RefMapFormatter slotFormatter = new DefaultRefMapFormatter(target.arch, target.wordSize, fp, 0);
78 for (Infopoint infopoint : compResult.getInfopoints()) {
79 if (infopoint instanceof Call) {
80 Call call = (Call) infopoint;
81 if (call.debugInfo != null) {
82 hcf.addComment(call.pcOffset + call.size, CodeUtil.append(new StringBuilder(100), call.debugInfo, slotFormatter).toString());
83 }
84 addOperandComment(hcf, call.pcOffset, "{" + getTargetName(call) + "}");
85 } else {
86 if (infopoint.debugInfo != null) {
87 hcf.addComment(infopoint.pcOffset, CodeUtil.append(new StringBuilder(100), infopoint.debugInfo, slotFormatter).toString());
88 }
89 addOperandComment(hcf, infopoint.pcOffset, "{infopoint: " + infopoint.reason + "}");
90 }
91 }
92 for (DataPatch site : compResult.getDataPatches()) {
93 hcf.addOperandComment(site.pcOffset, "{" + site.reference.toString() + "}");
94 }
95 for (Mark mark : compResult.getMarks()) {
96 hcf.addComment(mark.pcOffset, getMarkIdName((int) mark.id));
97 }
98 }
99 String hcfEmbeddedString = hcf.toEmbeddedString();
100 return HexCodeFileDisTool.tryDisassemble(hcfEmbeddedString);
101 }
102
103 /**
104 * Interface to the tool for disassembling an {@link HexCodeFile#toEmbeddedString() embedded}
105 * {@link HexCodeFile}.
106 */
107 static class HexCodeFileDisTool {
108 static final Method processMethod;
109 static {
110 Method toolMethod = null;
111 try {
112 Class<?> toolClass = Class.forName("com.oracle.max.hcfdis.HexCodeFileDis", true, ClassLoader.getSystemClassLoader());
113 toolMethod = toolClass.getDeclaredMethod("processEmbeddedString", String.class);
114 } catch (Exception e) {
115 // Tool not available on the class path
116 }
117 processMethod = toolMethod;
118 }
119
120 public static String tryDisassemble(String hcfEmbeddedString) {
121 if (processMethod != null) {
122 try {
123 return (String) processMethod.invoke(null, hcfEmbeddedString);
124 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
125 // If the tool is available, for now let's be noisy when it fails
126 throw new GraalInternalError(e);
127 }
128 }
129 return hcfEmbeddedString;
130 }
131 }
132
133 private String getMarkIdName(int markId) {
134 Field[] fields = runtime.getConfig().getClass().getDeclaredFields();
135 for (Field f : fields) {
136 if (f.getName().startsWith("MARKID_")) {
137 f.setAccessible(true);
138 try {
139 if (f.getInt(runtime.getConfig()) == markId) {
140 return f.getName();
141 }
142 } catch (Exception e) {
143 }
144 }
145 }
146 return String.valueOf(markId);
147 }
148
149 /**
150 * Decodes a call target to a mnemonic if possible.
151 */
152 private String getTargetName(Call call) {
153 Field[] fields = runtime.getConfig().getClass().getDeclaredFields();
154 for (Field f : fields) {
155 if (f.getName().endsWith("Stub")) {
156 f.setAccessible(true);
157 try {
158 Object address = f.get(runtime.getConfig());
159 if (address.equals(call.target)) {
160 return f.getName() + ":0x" + Long.toHexString((Long) address);
161 }
162 } catch (Exception e) {
163 }
164 }
165 }
166 return String.valueOf(call.target);
167 }
168
169 private static void addExceptionHandlersComment(CompilationResult compResult, HexCodeFile hcf) {
170 if (!compResult.getExceptionHandlers().isEmpty()) {
171 String nl = HexCodeFile.NEW_LINE;
172 StringBuilder buf = new StringBuilder("------ Exception Handlers ------").append(nl);
173 for (CompilationResult.ExceptionHandler e : compResult.getExceptionHandlers()) {
174 buf.append(" ").append(e.pcOffset).append(" -> ").append(e.handlerPos).append(nl);
175 hcf.addComment(e.pcOffset, "[exception -> " + e.handlerPos + "]");
176 hcf.addComment(e.handlerPos, "[exception handler for " + e.pcOffset + "]");
177 }
178 hcf.addComment(0, buf.toString());
179 }
180 }
181
182 private static void addOperandComment(HexCodeFile hcf, int pos, String comment) {
183 String oldValue = hcf.addOperandComment(pos, comment);
184 assert oldValue == null : "multiple comments for operand of instruction at " + pos + ": " + comment + ", " + oldValue;
185 }
186
187 @Override
188 public RegisterConfig getRegisterConfig() {
189 return regConfig;
190 }
191
192 @Override
193 public int getMinimumOutgoingSize() {
194 return runtime.getConfig().runtimeCallStackSize;
195 }
196
197 public InstalledCode logOrDump(InstalledCode installedCode, CompilationResult compResult) {
198 if (Debug.isDumpEnabled()) {
199 Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
200 }
201 if (Debug.isLogEnabled()) {
202 Debug.log("%s", disassemble(installedCode));
203 }
204 return installedCode;
205 }
206
207 public InstalledCode installMethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, long graalEnv, boolean isDefault) {
208 if (compResult.getId() == -1) {
209 compResult.setId(method.allocateCompileId(compResult.getEntryBCI()));
210 }
211 HotSpotInstalledCode installedCode = new HotSpotNmethod(method, compResult.getName(), isDefault);
212 runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(method, compResult, graalEnv), installedCode, method.getSpeculationLog());
213 return logOrDump(installedCode, compResult);
214 }
215
216 @Override
217 public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log, InstalledCode predefinedInstalledCode) {
218 HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
219 if (compResult.getId() == -1) {
220 compResult.setId(hotspotMethod.allocateCompileId(compResult.getEntryBCI()));
221 }
222 InstalledCode installedCode = predefinedInstalledCode;
223 if (installedCode == null) {
224 HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false);
225 installedCode = code;
226 }
227 HotSpotCompiledNmethod compiledCode = new HotSpotCompiledNmethod(hotspotMethod, compResult);
228 int result = runtime.getCompilerToVM().installCode(compiledCode, installedCode, log);
229 if (result != config.codeInstallResultOk) {
230 String msg = compiledCode.getInstallationFailureMessage();
231 String resultDesc = config.getCodeInstallResultDescription(result);
232 if (msg != null) {
233 msg = String.format("Code installation failed: %s%n%s", resultDesc, msg);
234 } else {
235 msg = String.format("Code installation failed: %s", resultDesc);
236 }
237 if (result == config.codeInstallResultDependenciesInvalid) {
238 throw new AssertionError(resultDesc + " " + msg);
239 }
240 throw new BailoutException(result != config.codeInstallResultDependenciesFailed, msg);
241 }
242 return logOrDump(installedCode, compResult);
243 }
244
245 @Override
246 public InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult) {
247 HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
248 return installMethod(hotspotMethod, compResult, 0L, true);
249 }
250
251 public HotSpotNmethod addExternalMethod(ResolvedJavaMethod method, CompilationResult compResult) {
252 HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) method;
253 if (compResult.getId() == -1) {
254 compResult.setId(javaMethod.allocateCompileId(compResult.getEntryBCI()));
255 }
256 HotSpotNmethod code = new HotSpotNmethod(javaMethod, compResult.getName(), false, true);
257 HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(javaMethod, compResult);
258 CompilerToVM vm = runtime.getCompilerToVM();
259 int result = vm.installCode(compiled, code, null);
260 if (result != runtime.getConfig().codeInstallResultOk) {
261 return null;
262 }
263 return code;
264 }
265
266 public boolean needsDataPatch(JavaConstant constant) {
267 return constant instanceof HotSpotMetaspaceConstant;
268 }
269
270 public Data createDataItem(Constant constant) {
271 int size;
272 DataBuilder builder;
273 if (constant instanceof VMConstant) {
274 VMConstant vmConstant = (VMConstant) constant;
275 boolean compressed;
276 long raw;
277 if (constant instanceof HotSpotObjectConstant) {
278 HotSpotObjectConstant c = (HotSpotObjectConstant) vmConstant;
279 compressed = c.isCompressed();
280 raw = 0xDEADDEADDEADDEADL;
281 } else if (constant instanceof HotSpotMetaspaceConstant) {
282 HotSpotMetaspaceConstant meta = (HotSpotMetaspaceConstant) constant;
283 compressed = meta.isCompressed();
284 raw = meta.rawValue();
285 } else {
286 throw GraalInternalError.shouldNotReachHere();
287 }
288
289 size = target.getSizeInBytes(compressed ? Kind.Int : target.wordKind);
290 if (size == 4) {
291 builder = (buffer, patch) -> {
292 patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant)));
293 buffer.putInt((int) raw);
294 };
295 } else {
296 assert size == 8;
297 builder = (buffer, patch) -> {
298 patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant)));
299 buffer.putLong(raw);
300 };
301 }
302 } else if (JavaConstant.isNull(constant)) {
303 boolean compressed = COMPRESSED_NULL.equals(constant);
304 size = target.getSizeInBytes(compressed ? Kind.Int : target.wordKind);
305 builder = DataBuilder.zero(size);
306 } else if (constant instanceof SerializableConstant) {
307 SerializableConstant s = (SerializableConstant) constant;
308 size = s.getSerializedSize();
309 builder = DataBuilder.serializable(s);
310 } else {
311 throw GraalInternalError.shouldNotReachHere();
312 }
313
314 return new Data(size, size, builder);
315 }
316
317 @Override
318 public TargetDescription getTarget() {
319 return target;
320 }
321
322 public String disassemble(InstalledCode code) {
323 if (code.isValid()) {
324 long codeBlob = code.getAddress();
325 return runtime.getCompilerToVM().disassembleCodeBlob(codeBlob);
326 }
327 return null;
328 }
329
330 public SpeculationLog createSpeculationLog() {
331 return new HotSpotSpeculationLog();
332 }
333 }