--- /dev/null 2016-05-31 09:42:47.975716356 -0700
+++ new/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CompilationPrinter.java 2016-12-09 00:56:37.715196788 -0800
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2011, 2015, 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 org.graalvm.compiler.printer;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.graalvm.compiler.debug.LogStream;
+import org.graalvm.compiler.debug.TTY;
+import org.graalvm.compiler.lir.util.IndexedValueMap;
+
+import jdk.vm.ci.code.BytecodeFrame;
+import jdk.vm.ci.code.BytecodePosition;
+import jdk.vm.ci.code.ReferenceMap;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterSaveLayout;
+import jdk.vm.ci.code.VirtualObject;
+import jdk.vm.ci.meta.JavaMethod;
+import jdk.vm.ci.meta.JavaValue;
+import jdk.vm.ci.meta.MetaUtil;
+
+/**
+ * Utility for printing compilation related data structures at various compilation phases. The
+ * output format is such that it can then be fed to the
+ * C1 Visualizer.
+ */
+public class CompilationPrinter implements Closeable {
+
+ 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();
+ }
+
+ @Override
+ public void close() {
+ out.out().close();
+ }
+
+ 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(JavaMethod method) {
+ begin("compilation");
+ out.print("name \" ").print(method.format("%H::%n")).println('"');
+ out.print("method \"").print(method.format("%f %r %H.%n(%p)")).println('"');
+ out.print("date ").println(System.currentTimeMillis());
+ end("compilation");
+ }
+
+ /**
+ * Formats given debug info as a multi line string.
+ */
+ protected String debugInfoToString(BytecodePosition codePos, ReferenceMap refMap, IndexedValueMap liveBasePointers, RegisterSaveLayout calleeSaveInfo) {
+ StringBuilder sb = new StringBuilder();
+ if (refMap != null) {
+ sb.append("reference-map: ");
+ sb.append(refMap.toString());
+ sb.append("\n");
+ }
+ if (liveBasePointers != null) {
+ sb.append("live-base-pointers: ");
+ sb.append(liveBasePointers);
+ sb.append("\n");
+ }
+
+ if (calleeSaveInfo != null) {
+ sb.append("callee-save-info:");
+ for (Map.Entry e : calleeSaveInfo.registersToSlots(true).entrySet()) {
+ sb.append(" " + e.getKey() + " -> s" + e.getValue());
+ }
+ sb.append("\n");
+ }
+
+ if (codePos != null) {
+ BytecodePosition curCodePos = codePos;
+ List virtualObjects = new ArrayList<>();
+ do {
+ sb.append(MetaUtil.toLocation(curCodePos.getMethod(), curCodePos.getBCI()));
+ sb.append('\n');
+ if (curCodePos instanceof BytecodeFrame) {
+ BytecodeFrame frame = (BytecodeFrame) curCodePos;
+ if (frame.numStack > 0) {
+ sb.append("stack: ");
+ for (int i = 0; i < frame.numStack; i++) {
+ sb.append(valueToString(frame.getStackValue(i), virtualObjects)).append(' ');
+ }
+ sb.append("\n");
+ }
+ sb.append("locals: ");
+ for (int i = 0; i < frame.numLocals; i++) {
+ sb.append(valueToString(frame.getLocalValue(i), virtualObjects)).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), virtualObjects)).append(' ');
+ }
+ sb.append("\n");
+ }
+
+ }
+ curCodePos = curCodePos.getCaller();
+ } while (curCodePos != null);
+
+ for (int i = 0; i < virtualObjects.size(); i++) {
+ VirtualObject obj = virtualObjects.get(i);
+ sb.append(obj).append(" ").append(obj.getType().getName()).append(" ");
+ for (int j = 0; j < obj.getValues().length; j++) {
+ sb.append(valueToString(obj.getValues()[j], virtualObjects)).append(' ');
+ }
+ sb.append("\n");
+
+ }
+ }
+ return sb.toString();
+ }
+
+ protected String valueToString(JavaValue value, List virtualObjects) {
+ if (value == null) {
+ return "-";
+ }
+ if (value instanceof VirtualObject && !virtualObjects.contains(value)) {
+ virtualObjects.add((VirtualObject) value);
+ }
+ return value.toString();
+ }
+
+ public void printMachineCode(String code, String label) {
+ if (code == null || 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 == null || code.length() == 0) {
+ return;
+ }
+ begin("bytecodes");
+ out.print(code);
+ out.println(" <|@");
+ end("bytecodes");
+ }
+}