comparison graal/com.oracle.max.criutils/src/com/oracle/max/criutils/CompilationPrinter.java @ 3733:e233f5660da4

Added Java files from Maxine project.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sat, 17 Dec 2011 19:59:18 +0100
parents
children bc8527f3071c
comparison
equal deleted inserted replaced
3732:3e2e8b8abdaf 3733:e233f5660da4
1 /*
2 * Copyright (c) 2011, 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.max.criutils;
24
25 import java.io.*;
26
27 import com.sun.cri.ci.*;
28 import com.sun.cri.ci.CiAddress.Scale;
29 import com.sun.cri.ci.CiValue.Formatter;
30 import com.sun.cri.ri.*;
31
32 /**
33 * Utility for printing compilation related data structures at various compilation phases.
34 * The output format is such that it can then be fed to the
35 * <a href="https://c1visualizer.dev.java.net/">C1 Visualizer</a>.
36 */
37 public class CompilationPrinter {
38 public static final String COLUMN_END = " <|@";
39 public static final String HOVER_START = "<@";
40 public static final String HOVER_SEP = "|@";
41 public static final String HOVER_END = ">@";
42
43 private static OutputStream globalOut;
44
45 /**
46 * Gets a global output stream on a file in the current working directory.
47 * This stream is first opened if necessary. The name of the file
48 * is {@code "compilations-" + System.currentTimeMillis() + ".cfg"}.
49 *
50 * @return the global output stream or {@code null} if there was an error opening the file for writing
51 */
52 public static synchronized OutputStream globalOut() {
53 if (globalOut == null) {
54 File file = new File("compilations-" + System.currentTimeMillis() + ".cfg");
55 try {
56 globalOut = new FileOutputStream(file);
57 } catch (FileNotFoundException e) {
58 TTY.println("WARNING: Could not open " + file.getAbsolutePath());
59 }
60 }
61 return globalOut;
62 }
63
64 protected final LogStream out;
65
66 /**
67 * Creates a control flow graph printer.
68 *
69 * @param os where the output generated via this printer will be sent
70 */
71 public CompilationPrinter(OutputStream os) {
72 out = new LogStream(os);
73 }
74
75 /**
76 * Flushes all buffered output to the underlying output stream.
77 */
78 public void flush() {
79 out.flush();
80 }
81
82 protected void begin(String string) {
83 out.println("begin_" + string);
84 out.adjustIndentation(2);
85 }
86
87 protected void end(String string) {
88 out.adjustIndentation(-2);
89 out.println("end_" + string);
90 }
91
92 /**
93 * Prints a compilation timestamp for a given method.
94 *
95 * @param method the method for which a timestamp will be printed
96 */
97 public void printCompilation(RiMethod method) {
98 begin("compilation");
99 out.print("name \" ").print(CiUtil.format("%H::%n", method, true)).println('"');
100 out.print("method \"").print(CiUtil.format("%f %r %H.%n(%p)", method, true)).println('"');
101 out.print("date ").println(System.currentTimeMillis());
102 end("compilation");
103 }
104
105 /**
106 * Formats a given {@linkplain FrameState JVM frame state} as a multi line string.
107 */
108 protected String debugInfoToString(CiCodePos codePos, CiBitMap registerRefMap, CiBitMap frameRefMap, OperandFormatter fmt, CiArchitecture arch) {
109 StringBuilder sb = new StringBuilder();
110
111 if (registerRefMap != null) {
112 sb.append("reg-ref-map:");
113 for (int reg = registerRefMap.nextSetBit(0); reg >= 0; reg = registerRefMap.nextSetBit(reg + 1)) {
114 sb.append(' ').append(arch == null ? "reg" + reg : arch.registers[reg]);
115 }
116 sb.append("\n");
117 }
118
119 if (frameRefMap != null) {
120 sb.append("frame-ref-map:");
121 for (int reg = frameRefMap.nextSetBit(0); reg >= 0; reg = frameRefMap.nextSetBit(reg + 1)) {
122 sb.append(' ').append(CiStackSlot.get(CiKind.Object, reg));
123 }
124 sb.append("\n");
125 }
126
127 if (codePos != null) {
128 do {
129 sb.append(CiUtil.toLocation(codePos.method, codePos.bci));
130 sb.append('\n');
131 if (codePos instanceof CiFrame) {
132 CiFrame frame = (CiFrame) codePos;
133 if (frame.numStack > 0) {
134 sb.append("stack: ");
135 for (int i = 0; i < frame.numStack; i++) {
136 sb.append(valueToString(frame.getStackValue(i), fmt)).append(' ');
137 }
138 sb.append("\n");
139 }
140
141 if (frame.numLocks > 0) {
142 sb.append("locks: ");
143 for (int i = 0; i < frame.numLocks; ++i) {
144 sb.append(valueToString(frame.getLockValue(i), fmt)).append(' ');
145 }
146 sb.append("\n");
147 }
148
149 sb.append("locals: ");
150 for (int i = 0; i < frame.numLocals; i++) {
151 sb.append(valueToString(frame.getLocalValue(i), fmt)).append(' ');
152 }
153 sb.append("\n");
154 }
155 codePos = codePos.caller;
156 } while (codePos != null);
157 }
158 return sb.toString();
159 }
160
161
162 protected String valueToString(CiValue value, Formatter operandFmt) {
163 if (value == null) {
164 return "-";
165 }
166 return operandFmt.format(value);
167 }
168
169
170 /**
171 * Formats LIR operands as expected by the C1 Visualizer.
172 */
173 public static class OperandFormatter extends Formatter {
174 /**
175 * The textual delimiters used for an operand depend on the context in which it is being
176 * printed. When printed as part of a frame state or as the result operand in a HIR node listing,
177 * it is enclosed in double-quotes (i.e. {@code "}'s).
178 */
179 public final boolean asStateOrHIROperandResult;
180
181 public OperandFormatter(boolean asStateOrHIROperandResult) {
182 this.asStateOrHIROperandResult = asStateOrHIROperandResult;
183 }
184
185 @Override
186 public String format(CiValue operand) {
187 if (operand.isLegal()) {
188 String op;
189 if (operand.isVariableOrRegister() || operand.isStackSlot()) {
190 op = operand.name();
191 } else if (operand.isConstant()) {
192 CiConstant constant = (CiConstant) operand;
193 op = operand.kind.javaName + ":" + operand.kind.format(constant.boxedValue());
194 } else if (operand.isAddress()) {
195 CiAddress address = (CiAddress) operand;
196 op = "Base:" + format(address.base);
197 if (!address.index.isIllegal()) {
198 op += " Index:" + format(address.index);
199 }
200 if (address.scale != Scale.Times1) {
201 op += " * " + address.scale.value;
202 }
203 op += " Disp:" + address.displacement;
204 } else {
205 assert operand.isIllegal();
206 op = "-";
207 }
208 if (operand.kind != CiKind.Illegal) {
209 op += "|" + operand.kind.typeChar;
210 }
211 if (asStateOrHIROperandResult) {
212 op = " \"" + op.replace('"', '\'') + "\" ";
213 }
214 return op;
215 }
216 return "";
217 }
218 }
219
220 public void printMachineCode(String code, String label) {
221 if (code.length() == 0) {
222 return;
223 }
224 if (label != null) {
225 begin("cfg");
226 out.print("name \"").print(label).println('"');
227 end("cfg");
228 }
229 begin("nmethod");
230 out.print(code);
231 out.println(" <|@");
232 end("nmethod");
233 }
234
235 public void printBytecodes(String code) {
236 if (code.length() == 0) {
237 return;
238 }
239 begin("bytecodes");
240 out.print(code);
241 out.println(" <|@");
242 end("bytecodes");
243 }
244 }