changeset 2684:ed36daed4c43

Add new option PrintIdealGraphToFile and another printer/observer pair to generate a graph representation that can be visualized and inspected with the ideal graph visualizer
author Peter Hofer <peter.hofer@jku.at>
date Mon, 16 May 2011 17:31:53 +0200
parents 026b21a81651
children 017253860bbb
files graal/GraalCompiler/src/com/sun/c1x/C1XCompiler.java graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinter.java graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinterObserver.java graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java
diffstat 5 files changed, 247 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/graal/GraalCompiler/src/com/sun/c1x/C1XCompiler.java	Mon May 16 17:26:47 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/C1XCompiler.java	Mon May 16 17:31:53 2011 +0200
@@ -131,6 +131,9 @@
         if (C1XOptions.PrintDOTGraphToPdf) {
             addCompilationObserver(new GraphvizPrinterObserver(true));
         }
+        if (C1XOptions.PrintIdealGraphToFile) {
+            addCompilationObserver(new IdealGraphPrinterObserver());
+        }
     }
 
     public GlobalStub lookupGlobalStub(GlobalStub.Id id) {
--- a/graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java	Mon May 16 17:26:47 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java	Mon May 16 17:31:53 2011 +0200
@@ -69,6 +69,7 @@
     public static boolean PrintCFGToFile                     = ____;
     public static boolean PrintDOTGraphToFile                = ____;
     public static boolean PrintDOTGraphToPdf                 = ____;
+    public static boolean PrintIdealGraphToFile              = ____;
     public static boolean OmitDOTFrameStates                 = true;
     public static boolean PrintMetrics                       = ____;
     public static boolean PrintTimers                        = ____;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinter.java	Mon May 16 17:31:53 2011 +0200
@@ -0,0 +1,152 @@
+/*
+ * 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.sun.c1x.debug;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+
+/**
+ * Generates a representation of {@link Graph Graphs} that can be visualized and inspected with the <a
+ * href="http://kenai.com/projects/igv">Ideal Graph Visualizer</a>.
+ */
+public class IdealGraphPrinter {
+
+    private static class Edge {
+        final int from;
+        final int to;
+        final int index;
+
+        Edge(int from, int to, int index) {
+            this.from = from;
+            this.to = to;
+            this.index = index;
+        }
+    }
+
+    private final HashSet<Class<?>> omittedClasses = new HashSet<Class<?>>();
+    private final PrintStream stream;
+
+    /**
+     * Creates a new {@link IdealGraphPrinter} that writes to the specified output stream.
+     */
+    public IdealGraphPrinter(OutputStream stream) {
+        this.stream = new PrintStream(stream);
+    }
+
+    /**
+     * Adds a node class that is omitted in the output.
+     */
+    public void addOmittedClass(Class<?> clazz) {
+        omittedClasses.add(clazz);
+    }
+
+    /**
+     * Starts a new graph document containing a single group of graphs with the given name, short name and byte code
+     * index (BCI) as properties.
+     */
+    public void begin(String name, String shortName, int bci) {
+        stream.println("<graphDocument><group>");
+        stream.printf(" <properties><p name='name'>%s</p></properties>%n", escape(name));
+        stream.printf(" <method name='%s' shortName='%s' bci='%d'/>%n", escape(name), escape(shortName), bci);
+    }
+
+    /**
+     * Finishes the graph document.
+     */
+    public void end() {
+        stream.println("</group></graphDocument>");
+        stream.flush();
+    }
+
+    /**
+     * Prints an entire {@link Graph} with the specified title, optionally using short names for nodes.
+     */
+    public void print(Graph graph, String title, boolean shortNames) {
+        stream.printf(" <graph name='%s'>%n", escape(title));
+
+        stream.println("  <nodes>");
+        List<Edge> edges = printNodes(graph.getNodes(), shortNames);
+        stream.println("  </nodes>");
+
+        stream.println("  <edges>");
+        for (Edge edge : edges) {
+            printEdge(edge);
+        }
+        stream.println("  </edges>");
+
+        stream.println(" </graph>");
+    }
+
+    private List<Edge> printNodes(Collection<Node> nodes, boolean shortNames) {
+        ArrayList<Edge> edges = new ArrayList<Edge>();
+
+        for (Node node : nodes) {
+            if (node == Node.Null || omittedClasses.contains(node)) {
+                continue;
+            }
+
+            String name;
+            if (shortNames) {
+                name = node.shortName();
+            } else {
+                name = node.toString();
+            }
+
+            stream.printf("   <node id='%d'><properties>", node.id());
+            stream.printf("<p name='idx'>%d</p>", node.id());
+            stream.printf("<p name='name'>%s</p>", escape(name));
+            stream.println("</properties></node>");
+
+            int index = 0;
+            for (Node predecessor : node.predecessors()) {
+                if (predecessor != Node.Null && !omittedClasses.contains(predecessor.getClass())) {
+                    edges.add(new Edge(predecessor.id(), node.id(), index));
+                }
+                index++;
+            }
+            for (Node input : node.inputs()) {
+                if (input != Node.Null && !omittedClasses.contains(input.getClass())) {
+                    edges.add(new Edge(input.id(), node.id(), index));
+                }
+                index++;
+            }
+        }
+
+        return edges;
+    }
+
+    private void printEdge(Edge edge) {
+        stream.printf("   <edge from='%d' to='%d' index='%d'/>%n", edge.from, edge.to, edge.index);
+    }
+
+    private String escape(String s) {
+        s = s.replace("&", "&amp;");
+        s = s.replace("<", "&lt;");
+        s = s.replace(">", "&gt;");
+        s = s.replace("\"", "&quot;");
+        s = s.replace("'", "&apos;");
+        return s;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinterObserver.java	Mon May 16 17:31:53 2011 +0200
@@ -0,0 +1,90 @@
+/*
+ * 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.sun.c1x.debug;
+
+import java.io.*;
+
+import com.oracle.graal.graph.*;
+import com.sun.c1x.*;
+import com.sun.c1x.observer.*;
+import com.sun.c1x.value.*;
+
+/**
+ * Observes compilation events and uses {@link IdealGraphPrinter} to generate a graph representation that can be
+ * inspected with the <a href="http://kenai.com/projects/igv">Ideal Graph Visualizer</a>.
+ * 
+ * @author Peter Hofer
+ */
+public class IdealGraphPrinterObserver implements CompilationObserver {
+
+    private IdealGraphPrinter printer;
+    private OutputStream stream;
+
+    @Override
+    public void compilationStarted(CompilationEvent event) {
+        assert (stream == null && printer == null);
+
+        if (!TTY.isSuppressed()) {
+            String name = event.getMethod().holder().name();
+            name = name.substring(1, name.length() - 1).replace('/', '.');
+            name = name + "." + event.getMethod().name();
+            String filename = name + ".igv.xml";
+            try {
+                stream = new FileOutputStream(filename);
+                printer = new IdealGraphPrinter(stream);
+
+                if (C1XOptions.OmitDOTFrameStates) {
+                    printer.addOmittedClass(FrameState.class);
+                }
+
+                printer.begin(name, name, -1);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    @Override
+    public void compilationEvent(CompilationEvent event) {
+        if (printer != null && event.getStartBlock() != null) {
+            Graph graph = event.getStartBlock().graph();
+            printer.print(graph, event.getLabel(), true);
+        }
+    }
+
+    @Override
+    public void compilationFinished(CompilationEvent event) {
+        if (printer != null) {
+            try {
+                printer.end();
+                stream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                printer = null;
+                stream = null;
+            }
+        }
+    }
+
+}
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Mon May 16 17:26:47 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Mon May 16 17:31:53 2011 +0200
@@ -150,7 +150,7 @@
         // 1. create the start block
         ir.startBlock = new BlockBegin(0, ir.nextBlockNumber(), graph);
         BlockBegin startBlock = ir.startBlock;
-//        graph.root().setStart(startBlock);
+        graph.root().setStart(startBlock);
 
         // 2. compute the block map, setup exception handlers and get the entrypoint(s)
         BlockMap blockMap = compilation.getBlockMap(rootMethod);