CompilationPrinter.java revision 12657:6ef01bd40ce2
1/* 2 * Copyright (c) 2011, 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 */ 23package org.graalvm.compiler.printer; 24 25import java.io.Closeable; 26import java.io.File; 27import java.io.FileNotFoundException; 28import java.io.FileOutputStream; 29import java.io.OutputStream; 30import java.util.ArrayList; 31import java.util.List; 32import java.util.Map; 33 34import org.graalvm.compiler.debug.LogStream; 35import org.graalvm.compiler.debug.TTY; 36import org.graalvm.compiler.lir.util.IndexedValueMap; 37 38import jdk.vm.ci.code.BytecodeFrame; 39import jdk.vm.ci.code.BytecodePosition; 40import jdk.vm.ci.code.ReferenceMap; 41import jdk.vm.ci.code.Register; 42import jdk.vm.ci.code.RegisterSaveLayout; 43import jdk.vm.ci.code.VirtualObject; 44import jdk.vm.ci.meta.JavaMethod; 45import jdk.vm.ci.meta.JavaValue; 46import jdk.vm.ci.meta.MetaUtil; 47 48/** 49 * Utility for printing compilation related data structures at various compilation phases. The 50 * output format is such that it can then be fed to the 51 * <a href="https://c1visualizer.dev.java.net/">C1 Visualizer</a>. 52 */ 53public class CompilationPrinter implements Closeable { 54 55 public static final String COLUMN_END = " <|@"; 56 public static final String HOVER_START = "<@"; 57 public static final String HOVER_SEP = "|@"; 58 public static final String HOVER_END = ">@"; 59 60 private static OutputStream globalOut; 61 62 /** 63 * Gets a global output stream on a file in the current working directory. This stream is first 64 * opened if necessary. The name of the file is 65 * {@code "compilations-" + System.currentTimeMillis() + ".cfg"}. 66 * 67 * @return the global output stream or {@code null} if there was an error opening the file for 68 * writing 69 */ 70 public static synchronized OutputStream globalOut() { 71 if (globalOut == null) { 72 File file = new File("compilations-" + System.currentTimeMillis() + ".cfg"); 73 try { 74 globalOut = new FileOutputStream(file); 75 } catch (FileNotFoundException e) { 76 TTY.println("WARNING: Could not open " + file.getAbsolutePath()); 77 } 78 } 79 return globalOut; 80 } 81 82 protected final LogStream out; 83 84 /** 85 * Creates a control flow graph printer. 86 * 87 * @param os where the output generated via this printer will be sent 88 */ 89 public CompilationPrinter(OutputStream os) { 90 out = new LogStream(os); 91 } 92 93 /** 94 * Flushes all buffered output to the underlying output stream. 95 */ 96 public void flush() { 97 out.flush(); 98 } 99 100 @Override 101 public void close() { 102 out.out().close(); 103 } 104 105 protected void begin(String string) { 106 out.println("begin_" + string); 107 out.adjustIndentation(2); 108 } 109 110 protected void end(String string) { 111 out.adjustIndentation(-2); 112 out.println("end_" + string); 113 } 114 115 /** 116 * Prints a compilation timestamp for a given method. 117 * 118 * @param method the method for which a timestamp will be printed 119 */ 120 public void printCompilation(JavaMethod method) { 121 begin("compilation"); 122 out.print("name \" ").print(method.format("%H::%n")).println('"'); 123 out.print("method \"").print(method.format("%f %r %H.%n(%p)")).println('"'); 124 out.print("date ").println(System.currentTimeMillis()); 125 end("compilation"); 126 } 127 128 /** 129 * Formats given debug info as a multi line string. 130 */ 131 protected String debugInfoToString(BytecodePosition codePos, ReferenceMap refMap, IndexedValueMap liveBasePointers, RegisterSaveLayout calleeSaveInfo) { 132 StringBuilder sb = new StringBuilder(); 133 if (refMap != null) { 134 sb.append("reference-map: "); 135 sb.append(refMap.toString()); 136 sb.append("\n"); 137 } 138 if (liveBasePointers != null) { 139 sb.append("live-base-pointers: "); 140 sb.append(liveBasePointers); 141 sb.append("\n"); 142 } 143 144 if (calleeSaveInfo != null) { 145 sb.append("callee-save-info:"); 146 for (Map.Entry<Register, Integer> e : calleeSaveInfo.registersToSlots(true).entrySet()) { 147 sb.append(" " + e.getKey() + " -> s" + e.getValue()); 148 } 149 sb.append("\n"); 150 } 151 152 if (codePos != null) { 153 BytecodePosition curCodePos = codePos; 154 List<VirtualObject> virtualObjects = new ArrayList<>(); 155 do { 156 sb.append(MetaUtil.toLocation(curCodePos.getMethod(), curCodePos.getBCI())); 157 sb.append('\n'); 158 if (curCodePos instanceof BytecodeFrame) { 159 BytecodeFrame frame = (BytecodeFrame) curCodePos; 160 if (frame.numStack > 0) { 161 sb.append("stack: "); 162 for (int i = 0; i < frame.numStack; i++) { 163 sb.append(valueToString(frame.getStackValue(i), virtualObjects)).append(' '); 164 } 165 sb.append("\n"); 166 } 167 sb.append("locals: "); 168 for (int i = 0; i < frame.numLocals; i++) { 169 sb.append(valueToString(frame.getLocalValue(i), virtualObjects)).append(' '); 170 } 171 sb.append("\n"); 172 if (frame.numLocks > 0) { 173 sb.append("locks: "); 174 for (int i = 0; i < frame.numLocks; ++i) { 175 sb.append(valueToString(frame.getLockValue(i), virtualObjects)).append(' '); 176 } 177 sb.append("\n"); 178 } 179 180 } 181 curCodePos = curCodePos.getCaller(); 182 } while (curCodePos != null); 183 184 for (int i = 0; i < virtualObjects.size(); i++) { 185 VirtualObject obj = virtualObjects.get(i); 186 sb.append(obj).append(" ").append(obj.getType().getName()).append(" "); 187 for (int j = 0; j < obj.getValues().length; j++) { 188 sb.append(valueToString(obj.getValues()[j], virtualObjects)).append(' '); 189 } 190 sb.append("\n"); 191 192 } 193 } 194 return sb.toString(); 195 } 196 197 protected String valueToString(JavaValue value, List<VirtualObject> virtualObjects) { 198 if (value == null) { 199 return "-"; 200 } 201 if (value instanceof VirtualObject && !virtualObjects.contains(value)) { 202 virtualObjects.add((VirtualObject) value); 203 } 204 return value.toString(); 205 } 206 207 public void printMachineCode(String code, String label) { 208 if (code == null || code.length() == 0) { 209 return; 210 } 211 if (label != null) { 212 begin("cfg"); 213 out.print("name \"").print(label).println('"'); 214 end("cfg"); 215 } 216 begin("nmethod"); 217 out.print(code); 218 out.println(" <|@"); 219 end("nmethod"); 220 } 221 222 public void printBytecodes(String code) { 223 if (code == null || code.length() == 0) { 224 return; 225 } 226 begin("bytecodes"); 227 out.print(code); 228 out.println(" <|@"); 229 end("bytecodes"); 230 } 231} 232