/*
* 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.graal.compiler.debug;
import java.io.*;
import java.util.regex.*;
import com.oracle.max.criutils.*;
import com.oracle.max.graal.compiler.*;
import com.oracle.max.graal.compiler.observer.*;
import com.oracle.max.graal.graph.*;
import com.oracle.max.graal.graphviz.*;
import com.oracle.max.graal.nodes.*;
/**
* Observes compilation events and uses {@link GraphvizPrinter} to produce a control flow graph in the DOT language
* which can be visualized with Graphviz.
*/
public class GraphvizPrinterObserver implements CompilationObserver {
private static final Pattern INVALID_CHAR = Pattern.compile("[^A-Za-z0-9_.-]");
private final boolean pdf;
private String methodName;
private int n;
public GraphvizPrinterObserver(boolean pdf) {
this.pdf = pdf;
}
public void compilationStarted(GraalCompilation compilation) {
String name = compilation.method.holder().name();
name = name.substring(1, name.length() - 1).replace('/', '.');
name = name + "." + compilation.method.name();
methodName = name;
n = 0;
}
public void compilationFinished(GraalCompilation compilation) {
}
public void compilationEvent(CompilationEvent event) {
if (TTY.isSuppressed()) {
return;
}
Graph graph = event.debugObject(Graph.class);
if (graph != null) {
String filename = methodName + "_" + (n++) + "_" + event.label;
filename = INVALID_CHAR.matcher(filename).replaceAll("_");
OutputStream out = null;
try {
if (pdf) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
printGraph(graph, methodName, buffer);
out = new FileOutputStream(filename + ".pdf");
GraphvizRunner.process(GraphvizRunner.DOT_LAYOUT, new ByteArrayInputStream(buffer.toByteArray()), out, "pdf");
} else {
out = new FileOutputStream(filename + ".gv");
printGraph(graph, methodName, out);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
}
}
}
}
}
private static void printGraph(Graph graph, String name, OutputStream buffer) {
GraphvizPrinter printer = new GraphvizPrinter(buffer);
if (GraalOptions.OmitDOTFrameStates) {
printer.addOmittedClass(FrameState.class);
}
printer.addClassColor(LoopBeginNode.class, "skyblue");
printer.addClassColor(LoopEndNode.class, "skyblue3");
printer.addClassColor(UnwindNode.class, "red");
printer.addClassColor(ReturnNode.class, "indianred1");
printer.begin(name);
printer.print(graph, true);
printer.end();
}
}