comparison graal/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotCodeCacheProvider.java @ 21706:4c00096fc415

moved CodeCacheProvider.disassemble(...) from API to CFGPrinterObserver
author Doug Simon <doug.simon@oracle.com>
date Wed, 03 Jun 2015 16:52:41 +0200
parents d563baeca9df
children
comparison
equal deleted inserted replaced
21705:729e6acde6c0 21706:4c00096fc415
23 package com.oracle.jvmci.hotspot; 23 package com.oracle.jvmci.hotspot;
24 24
25 import static com.oracle.jvmci.hotspot.HotSpotCompressedNullConstant.*; 25 import static com.oracle.jvmci.hotspot.HotSpotCompressedNullConstant.*;
26 26
27 import java.lang.reflect.*; 27 import java.lang.reflect.*;
28 import java.util.*;
29 28
30 import com.oracle.jvmci.code.*; 29 import com.oracle.jvmci.code.*;
31 import com.oracle.jvmci.code.CodeUtil.DefaultRefMapFormatter;
32 import com.oracle.jvmci.code.CodeUtil.RefMapFormatter;
33 import com.oracle.jvmci.code.CompilationResult.Call; 30 import com.oracle.jvmci.code.CompilationResult.Call;
34 import com.oracle.jvmci.code.CompilationResult.ConstantReference; 31 import com.oracle.jvmci.code.CompilationResult.ConstantReference;
35 import com.oracle.jvmci.code.CompilationResult.DataPatch; 32 import com.oracle.jvmci.code.CompilationResult.DataPatch;
36 import com.oracle.jvmci.code.CompilationResult.Infopoint;
37 import com.oracle.jvmci.code.CompilationResult.Mark; 33 import com.oracle.jvmci.code.CompilationResult.Mark;
38 import com.oracle.jvmci.code.DataSection.Data; 34 import com.oracle.jvmci.code.DataSection.Data;
39 import com.oracle.jvmci.code.DataSection.DataBuilder; 35 import com.oracle.jvmci.code.DataSection.DataBuilder;
40 import com.oracle.jvmci.common.*; 36 import com.oracle.jvmci.common.*;
41 import com.oracle.jvmci.debug.*; 37 import com.oracle.jvmci.debug.*;
57 this.target = target; 53 this.target = target;
58 this.regConfig = regConfig; 54 this.regConfig = regConfig;
59 } 55 }
60 56
61 @Override 57 @Override
62 public String disassemble(CompilationResult compResult, InstalledCode installedCode) { 58 public String getMarkName(Mark mark) {
63 byte[] code = installedCode == null ? Arrays.copyOf(compResult.getTargetCode(), compResult.getTargetCodeSize()) : installedCode.getCode(); 59 int markId = (int) mark.id;
64 if (code == null) {
65 // Method was deoptimized/invalidated
66 return "";
67 }
68 long start = installedCode == null ? 0L : installedCode.getStart();
69 HexCodeFile hcf = new HexCodeFile(code, start, target.arch.getName(), target.wordSize * 8);
70 if (compResult != null) {
71 HexCodeFile.addAnnotations(hcf, compResult.getAnnotations());
72 addExceptionHandlersComment(compResult, hcf);
73 Register fp = regConfig.getFrameRegister();
74 RefMapFormatter slotFormatter = new DefaultRefMapFormatter(target.arch, target.wordSize, fp, 0);
75 for (Infopoint infopoint : compResult.getInfopoints()) {
76 if (infopoint instanceof Call) {
77 Call call = (Call) infopoint;
78 if (call.debugInfo != null) {
79 hcf.addComment(call.pcOffset + call.size, CodeUtil.append(new StringBuilder(100), call.debugInfo, slotFormatter).toString());
80 }
81 addOperandComment(hcf, call.pcOffset, "{" + getTargetName(call) + "}");
82 } else {
83 if (infopoint.debugInfo != null) {
84 hcf.addComment(infopoint.pcOffset, CodeUtil.append(new StringBuilder(100), infopoint.debugInfo, slotFormatter).toString());
85 }
86 addOperandComment(hcf, infopoint.pcOffset, "{infopoint: " + infopoint.reason + "}");
87 }
88 }
89 for (DataPatch site : compResult.getDataPatches()) {
90 hcf.addOperandComment(site.pcOffset, "{" + site.reference.toString() + "}");
91 }
92 for (Mark mark : compResult.getMarks()) {
93 hcf.addComment(mark.pcOffset, getMarkIdName((int) mark.id));
94 }
95 }
96 String hcfEmbeddedString = hcf.toEmbeddedString();
97 return HexCodeFileDisTool.tryDisassemble(hcfEmbeddedString);
98 }
99
100 /**
101 * Interface to the tool for disassembling an {@link HexCodeFile#toEmbeddedString() embedded}
102 * {@link HexCodeFile}.
103 */
104 static class HexCodeFileDisTool {
105 static final Method processMethod;
106 static {
107 Method toolMethod = null;
108 try {
109 Class<?> toolClass = Class.forName("com.oracle.max.hcfdis.HexCodeFileDis", true, ClassLoader.getSystemClassLoader());
110 toolMethod = toolClass.getDeclaredMethod("processEmbeddedString", String.class);
111 } catch (Exception e) {
112 // Tool not available on the class path
113 }
114 processMethod = toolMethod;
115 }
116
117 public static String tryDisassemble(String hcfEmbeddedString) {
118 if (processMethod != null) {
119 try {
120 return (String) processMethod.invoke(null, hcfEmbeddedString);
121 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
122 // If the tool is available, for now let's be noisy when it fails
123 throw new JVMCIError(e);
124 }
125 }
126 return hcfEmbeddedString;
127 }
128 }
129
130 private String getMarkIdName(int markId) {
131 Field[] fields = runtime.getConfig().getClass().getDeclaredFields(); 60 Field[] fields = runtime.getConfig().getClass().getDeclaredFields();
132 for (Field f : fields) { 61 for (Field f : fields) {
133 if (f.getName().startsWith("MARKID_")) { 62 if (f.getName().startsWith("MARKID_")) {
134 f.setAccessible(true); 63 f.setAccessible(true);
135 try { 64 try {
138 } 67 }
139 } catch (Exception e) { 68 } catch (Exception e) {
140 } 69 }
141 } 70 }
142 } 71 }
143 return String.valueOf(markId); 72 return CodeCacheProvider.super.getMarkName(mark);
144 } 73 }
145 74
146 /** 75 /**
147 * Decodes a call target to a mnemonic if possible. 76 * Decodes a call target to a mnemonic if possible.
148 */ 77 */
149 private String getTargetName(Call call) { 78 @Override
79 public String getTargetName(Call call) {
150 Field[] fields = runtime.getConfig().getClass().getDeclaredFields(); 80 Field[] fields = runtime.getConfig().getClass().getDeclaredFields();
151 for (Field f : fields) { 81 for (Field f : fields) {
152 if (f.getName().endsWith("Stub")) { 82 if (f.getName().endsWith("Stub")) {
153 f.setAccessible(true); 83 f.setAccessible(true);
154 try { 84 try {
158 } 88 }
159 } catch (Exception e) { 89 } catch (Exception e) {
160 } 90 }
161 } 91 }
162 } 92 }
163 return String.valueOf(call.target); 93 return CodeCacheProvider.super.getTargetName(call);
164 }
165
166 private static void addExceptionHandlersComment(CompilationResult compResult, HexCodeFile hcf) {
167 if (!compResult.getExceptionHandlers().isEmpty()) {
168 String nl = HexCodeFile.NEW_LINE;
169 StringBuilder buf = new StringBuilder("------ Exception Handlers ------").append(nl);
170 for (CompilationResult.ExceptionHandler e : compResult.getExceptionHandlers()) {
171 buf.append(" ").append(e.pcOffset).append(" -> ").append(e.handlerPos).append(nl);
172 hcf.addComment(e.pcOffset, "[exception -> " + e.handlerPos + "]");
173 hcf.addComment(e.handlerPos, "[exception handler for " + e.pcOffset + "]");
174 }
175 hcf.addComment(0, buf.toString());
176 }
177 }
178
179 private static void addOperandComment(HexCodeFile hcf, int pos, String comment) {
180 String oldValue = hcf.addOperandComment(pos, comment);
181 assert oldValue == null : "multiple comments for operand of instruction at " + pos + ": " + comment + ", " + oldValue;
182 } 94 }
183 95
184 @Override 96 @Override
185 public RegisterConfig getRegisterConfig() { 97 public RegisterConfig getRegisterConfig() {
186 return regConfig; 98 return regConfig;