Mercurial > hg > graal-compiler
view graal/com.oracle.max.criutils/src/com/oracle/max/criutils/CompilationPrinter.java @ 3736:d3ec27ea1b20
Work with GRAAL environment variable instead of MAXINE environment variable.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Sat, 17 Dec 2011 20:48:46 +0100 |
parents | e233f5660da4 |
children | bc8527f3071c |
line wrap: on
line source
/* * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.oracle.max.criutils; import java.io.*; import com.sun.cri.ci.*; import com.sun.cri.ci.CiAddress.Scale; import com.sun.cri.ci.CiValue.Formatter; import com.sun.cri.ri.*; /** * Utility for printing compilation related data structures at various compilation phases. * The output format is such that it can then be fed to the * <a href="https://c1visualizer.dev.java.net/">C1 Visualizer</a>. */ public class CompilationPrinter { public static final String COLUMN_END = " <|@"; public static final String HOVER_START = "<@"; public static final String HOVER_SEP = "|@"; public static final String HOVER_END = ">@"; private static OutputStream globalOut; /** * Gets a global output stream on a file in the current working directory. * This stream is first opened if necessary. The name of the file * is {@code "compilations-" + System.currentTimeMillis() + ".cfg"}. * * @return the global output stream or {@code null} if there was an error opening the file for writing */ public static synchronized OutputStream globalOut() { if (globalOut == null) { File file = new File("compilations-" + System.currentTimeMillis() + ".cfg"); try { globalOut = new FileOutputStream(file); } catch (FileNotFoundException e) { TTY.println("WARNING: Could not open " + file.getAbsolutePath()); } } return globalOut; } protected final LogStream out; /** * Creates a control flow graph printer. * * @param os where the output generated via this printer will be sent */ public CompilationPrinter(OutputStream os) { out = new LogStream(os); } /** * Flushes all buffered output to the underlying output stream. */ public void flush() { out.flush(); } protected void begin(String string) { out.println("begin_" + string); out.adjustIndentation(2); } protected void end(String string) { out.adjustIndentation(-2); out.println("end_" + string); } /** * Prints a compilation timestamp for a given method. * * @param method the method for which a timestamp will be printed */ public void printCompilation(RiMethod method) { begin("compilation"); out.print("name \" ").print(CiUtil.format("%H::%n", method, true)).println('"'); out.print("method \"").print(CiUtil.format("%f %r %H.%n(%p)", method, true)).println('"'); out.print("date ").println(System.currentTimeMillis()); end("compilation"); } /** * Formats a given {@linkplain FrameState JVM frame state} as a multi line string. */ protected String debugInfoToString(CiCodePos codePos, CiBitMap registerRefMap, CiBitMap frameRefMap, OperandFormatter fmt, CiArchitecture arch) { StringBuilder sb = new StringBuilder(); if (registerRefMap != null) { sb.append("reg-ref-map:"); for (int reg = registerRefMap.nextSetBit(0); reg >= 0; reg = registerRefMap.nextSetBit(reg + 1)) { sb.append(' ').append(arch == null ? "reg" + reg : arch.registers[reg]); } sb.append("\n"); } if (frameRefMap != null) { sb.append("frame-ref-map:"); for (int reg = frameRefMap.nextSetBit(0); reg >= 0; reg = frameRefMap.nextSetBit(reg + 1)) { sb.append(' ').append(CiStackSlot.get(CiKind.Object, reg)); } sb.append("\n"); } if (codePos != null) { do { sb.append(CiUtil.toLocation(codePos.method, codePos.bci)); sb.append('\n'); if (codePos instanceof CiFrame) { CiFrame frame = (CiFrame) codePos; if (frame.numStack > 0) { sb.append("stack: "); for (int i = 0; i < frame.numStack; i++) { sb.append(valueToString(frame.getStackValue(i), fmt)).append(' '); } sb.append("\n"); } if (frame.numLocks > 0) { sb.append("locks: "); for (int i = 0; i < frame.numLocks; ++i) { sb.append(valueToString(frame.getLockValue(i), fmt)).append(' '); } sb.append("\n"); } sb.append("locals: "); for (int i = 0; i < frame.numLocals; i++) { sb.append(valueToString(frame.getLocalValue(i), fmt)).append(' '); } sb.append("\n"); } codePos = codePos.caller; } while (codePos != null); } return sb.toString(); } protected String valueToString(CiValue value, Formatter operandFmt) { if (value == null) { return "-"; } return operandFmt.format(value); } /** * Formats LIR operands as expected by the C1 Visualizer. */ public static class OperandFormatter extends Formatter { /** * The textual delimiters used for an operand depend on the context in which it is being * printed. When printed as part of a frame state or as the result operand in a HIR node listing, * it is enclosed in double-quotes (i.e. {@code "}'s). */ public final boolean asStateOrHIROperandResult; public OperandFormatter(boolean asStateOrHIROperandResult) { this.asStateOrHIROperandResult = asStateOrHIROperandResult; } @Override public String format(CiValue operand) { if (operand.isLegal()) { String op; if (operand.isVariableOrRegister() || operand.isStackSlot()) { op = operand.name(); } else if (operand.isConstant()) { CiConstant constant = (CiConstant) operand; op = operand.kind.javaName + ":" + operand.kind.format(constant.boxedValue()); } else if (operand.isAddress()) { CiAddress address = (CiAddress) operand; op = "Base:" + format(address.base); if (!address.index.isIllegal()) { op += " Index:" + format(address.index); } if (address.scale != Scale.Times1) { op += " * " + address.scale.value; } op += " Disp:" + address.displacement; } else { assert operand.isIllegal(); op = "-"; } if (operand.kind != CiKind.Illegal) { op += "|" + operand.kind.typeChar; } if (asStateOrHIROperandResult) { op = " \"" + op.replace('"', '\'') + "\" "; } return op; } return ""; } } public void printMachineCode(String code, String label) { if (code.length() == 0) { return; } if (label != null) { begin("cfg"); out.print("name \"").print(label).println('"'); end("cfg"); } begin("nmethod"); out.print(code); out.println(" <|@"); end("nmethod"); } public void printBytecodes(String code) { if (code.length() == 0) { return; } begin("bytecodes"); out.print(code); out.println(" <|@"); end("bytecodes"); } }