# HG changeset patch # User Peter Hofer # Date 1305559913 -7200 # Node ID ed36daed4c4386ec614bf91439c6923b1dc74273 # Parent 026b21a81651c9ff90c92d8fa995d1b31632bddd 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 diff -r 026b21a81651 -r ed36daed4c43 graal/GraalCompiler/src/com/sun/c1x/C1XCompiler.java --- 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) { diff -r 026b21a81651 -r ed36daed4c43 graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java --- 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 = ____; diff -r 026b21a81651 -r ed36daed4c43 graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinter.java --- /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 Ideal Graph Visualizer. + */ +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> omittedClasses = new HashSet>(); + 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(""); + stream.printf("

%s

%n", escape(name)); + stream.printf(" %n", escape(name), escape(shortName), bci); + } + + /** + * Finishes the graph document. + */ + public void end() { + stream.println("
"); + 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(" %n", escape(title)); + + stream.println(" "); + List edges = printNodes(graph.getNodes(), shortNames); + stream.println(" "); + + stream.println(" "); + for (Edge edge : edges) { + printEdge(edge); + } + stream.println(" "); + + stream.println(" "); + } + + private List printNodes(Collection nodes, boolean shortNames) { + ArrayList edges = new ArrayList(); + + 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()); + stream.printf("

%d

", node.id()); + stream.printf("

%s

", escape(name)); + stream.println("
"); + + 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(" %n", edge.from, edge.to, edge.index); + } + + private String escape(String s) { + s = s.replace("&", "&"); + s = s.replace("<", "<"); + s = s.replace(">", ">"); + s = s.replace("\"", """); + s = s.replace("'", "'"); + return s; + } +} diff -r 026b21a81651 -r ed36daed4c43 graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinterObserver.java --- /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 Ideal Graph Visualizer. + * + * @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; + } + } + } + +} diff -r 026b21a81651 -r ed36daed4c43 graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java --- 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);