# HG changeset patch # User Gilles Duboscq # Date 1341836155 -7200 # Node ID bc237d8b6f99f4b649675cec7bc18e2b525159d0 # Parent cb5fd04e95b3a51d155676c7e16b8d5f2db227be Add binary graph dumping to compiler (-G:+PrintBinaryGraphs) Add binary graph handling in IGV (runs in parallel with xml graph handling) Add option to disable CFG files (c1 visualizer) dumping Include partial schedule in igv dumps when graph is not schedulable diff -r cb5fd04e95b3 -r bc237d8b6f99 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Wed Jul 04 15:27:28 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Mon Jul 09 14:15:55 2012 +0200 @@ -135,11 +135,13 @@ public static boolean DumpOnError = ____; // Ideal graph visualizer output settings + public static boolean PrintBinaryGraphs = ____; + public static boolean PrintCFG = true; public static int PlotLevel = 3; - public static int PrintIdealGraphLevel = 0; public static boolean PrintIdealGraphFile = ____; public static String PrintIdealGraphAddress = "127.0.0.1"; public static int PrintIdealGraphPort = 4444; + public static int PrintBinaryGraphPort = 4445; // Other printing settings public static boolean PrintQueue = ____; @@ -210,6 +212,7 @@ public static boolean OptLivenessAnalysis = true; public static boolean OptLoopTransform = true; public static boolean OptSafepointElimination = true; + public static boolean FloatingReads = true; /** * Insert a counter in the method prologue to track the most frequently called methods that were compiled by Graal. diff -r cb5fd04e95b3 -r bc237d8b6f99 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/graph/PostOrderNodeIterator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/graph/PostOrderNodeIterator.java Wed Jul 04 15:27:28 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/graph/PostOrderNodeIterator.java Mon Jul 09 14:15:55 2012 +0200 @@ -27,6 +27,14 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +/** + * A PostOrderNodeIterator iterates the fixed nodes of the graph in post order starting from a specified fixed node.
+ * For this iterator the CFG is defined by the classical CFG nodes ({@link ControlSplitNode}, {@link MergeNode}...) and the {@link FixedWithNextNode#next() next} pointers + * of {@link FixedWithNextNode}.
+ * While iterating it maintains a user-defined state by calling the methods available in {@link MergeableState}. + * + * @param the type of {@link MergeableState} handled by this PostOrderNodeIterator + */ public abstract class PostOrderNodeIterator> { private final NodeBitMap visitedEnds; diff -r cb5fd04e95b3 -r bc237d8b6f99 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Wed Jul 04 15:27:28 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Mon Jul 09 14:15:55 2012 +0200 @@ -311,6 +311,11 @@ } return super.filter(clazz); } + + @Override + public int count() { + return getNodeCount(); + } }; } diff -r cb5fd04e95b3 -r bc237d8b6f99 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Wed Jul 04 15:27:28 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Mon Jul 09 14:15:55 2012 +0200 @@ -489,6 +489,12 @@ } } + + @Deprecated + public int getId() { + return id; + } + @Override public void formatTo(Formatter formatter, int flags, int width, int precision) { if ((flags & FormattableFlags.ALTERNATE) == FormattableFlags.ALTERNATE) { diff -r cb5fd04e95b3 -r bc237d8b6f99 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Wed Jul 04 15:27:28 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Mon Jul 09 14:15:55 2012 +0200 @@ -570,17 +570,6 @@ } else { assert false : "unhandled property type: " + type; } - } else { - value = unsafe.getObject(node, dataOffsets[i]); - if (type.isArray()) { - if (!type.getComponentType().isPrimitive()) { - value = Arrays.toString((Object[]) value); - } else if (type.getComponentType() == Integer.TYPE) { - value = Arrays.toString((int[]) value); - } else if (type.getComponentType() == Double.TYPE) { - value = Arrays.toString((double[]) value); - } - } } properties.put("data." + dataNames[i], value); } diff -r cb5fd04e95b3 -r bc237d8b6f99 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java Wed Jul 04 15:27:28 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java Mon Jul 09 14:15:55 2012 +0200 @@ -64,13 +64,22 @@ if (logFilter != null || meterFilter != null || timerFilter != null || dumpFilter != null || methodFilter != null) { TTY.println(Thread.currentThread().getName() + ": " + toString()); } - - if (GraalOptions.PrintIdealGraphFile) { - dumpHandlers.add(new IdealGraphPrinterDumpHandler()); + if (GraalOptions.PrintBinaryGraphs) { + if (GraalOptions.PrintIdealGraphFile) { + dumpHandlers.add(new BinaryGraphPrinterDumpHandler()); + } else { + dumpHandlers.add(new BinaryGraphPrinterDumpHandler(GraalOptions.PrintIdealGraphAddress, GraalOptions.PrintBinaryGraphPort)); + } } else { - dumpHandlers.add(new IdealGraphPrinterDumpHandler(GraalOptions.PrintIdealGraphAddress, GraalOptions.PrintIdealGraphPort)); + if (GraalOptions.PrintIdealGraphFile) { + dumpHandlers.add(new IdealGraphPrinterDumpHandler()); + } else { + dumpHandlers.add(new IdealGraphPrinterDumpHandler(GraalOptions.PrintIdealGraphAddress, GraalOptions.PrintIdealGraphPort)); + } } - dumpHandlers.add(new CFGPrinterObserver()); + if (GraalOptions.PrintCFG) { + dumpHandlers.add(new CFGPrinterObserver()); + } this.output = output; } diff -r cb5fd04e95b3 -r bc237d8b6f99 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/Block.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/Block.java Wed Jul 04 15:27:28 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/Block.java Mon Jul 09 14:15:55 2012 +0200 @@ -53,7 +53,6 @@ } public int getId() { - assert id >= 0; return id; } diff -r cb5fd04e95b3 -r bc237d8b6f99 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/CFGVerifier.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/CFGVerifier.java Wed Jul 04 15:27:28 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/CFGVerifier.java Mon Jul 09 14:15:55 2012 +0200 @@ -25,6 +25,7 @@ public class CFGVerifier { public static boolean verify(ControlFlowGraph cfg) { for (Block block : cfg.getBlocks()) { + assert block.getId() >= 0; assert cfg.getBlocks()[block.getId()] == block; for (Block pred : block.getPredecessors()) { diff -r cb5fd04e95b3 -r bc237d8b6f99 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Mon Jul 09 14:15:55 2012 +0200 @@ -0,0 +1,481 @@ +/* + * 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.graal.printer; + +import java.io.*; +import java.nio.*; +import java.nio.channels.*; +import java.util.*; +import java.util.Map.Entry; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.schedule.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.Verbosity; +import com.oracle.graal.graph.NodeClass.NodeClassIterator; +import com.oracle.graal.graph.NodeClass.Position; +import com.oracle.graal.lir.cfg.*; +import com.oracle.graal.nodes.*; + +public class BinaryGraphPrinter { + private static final int CONSTANT_POOL_MAX_SIZE = 2000; + + private static final int BEGIN_GROUP = 0x00; + private static final int BEGIN_GRAPH = 0x01; + private static final int CLOSE_GROUP = 0x02; + + private static final int POOL_NULL = -1; + private static final int POOL_NEW = 0x00; + private static final int POOL_STRING = 0x01; + private static final int POOL_ENUM = 0x02; + private static final int POOL_CLASS = 0x03; + private static final int POOL_METHOD = 0x04; + + private static final int PROPERTY_POOL = 0x00; + private static final int PROPERTY_INT = 0x01; + private static final int PROPERTY_LONG = 0x02; + private static final int PROPERTY_DOUBLE = 0x03; + private static final int PROPERTY_FLOAT = 0x04; + private static final int PROPERTY_TRUE = 0x05; + private static final int PROPERTY_FALSE = 0x06; + private static final int PROPERTY_ARRAY = 0x07; + + private static final int KLASS = 0x00; + private static final int ENUM_KLASS = 0x01; + + protected static class Edge { + final int from; + final char fromIndex; + final int to; + final char toIndex; + final String label; + + public Edge(int from, char fromIndex, int to, char toIndex, String label) { + this.from = from; + this.fromIndex = fromIndex; + this.to = to; + this.toIndex = toIndex; + this.label = label; + } + + @Override + public int hashCode() { + int h = from ^ to; + h = 3 * h + fromIndex; + h = 5 * h + toIndex; + if (label != null) { + h ^= label.hashCode(); + } + return h; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof Edge) { + Edge other = (Edge) obj; + return from == other.from + && fromIndex == other.fromIndex + && to == other.to + && toIndex == other.toIndex + && (label == other.label || (label != null && label.equals(other.label))); + } + return false; + } + } + + private static final class CosntantPool extends LinkedHashMap { + private final LinkedList availableIds; + private int nextId; + private static final long serialVersionUID = -2676889957907285681L; + public CosntantPool() { + super(50, 0.65f); + availableIds = new LinkedList<>(); + } + @Override + protected boolean removeEldestEntry(java.util.Map.Entry eldest) { + if (size() > CONSTANT_POOL_MAX_SIZE) { + availableIds.addFirst(eldest.getValue()); + return true; + } + return false; + } + + private Integer nextAvailableId() { + if (!availableIds.isEmpty()) { + return availableIds.removeFirst(); + } + return nextId++; + } + + public int add(Object obj) { + Integer id = nextAvailableId(); + put(obj, id); + return id; + } + } + + private final CosntantPool constantPool; + + + private final ByteBuffer buffer; + private final WritableByteChannel channel; + + + public BinaryGraphPrinter(WritableByteChannel channel) { + constantPool = new CosntantPool(); + buffer = ByteBuffer.allocateDirect(64 * 1024); + this.channel = channel; + } + + public void print(Graph graph, String title, SchedulePhase predefinedSchedule) throws IOException { + Set noBlockNodes = new HashSet<>(); + SchedulePhase schedule = predefinedSchedule; + if (schedule == null) { + try { + schedule = new SchedulePhase(); + schedule.apply((StructuredGraph) graph); + } catch (Throwable t) { + } + } + ControlFlowGraph cfg = schedule == null ? null : schedule.getCFG(); + + BlockMap> blockToNodes = schedule == null ? null : schedule.getBlockToNodesMap(); + writeByte(BEGIN_GRAPH); + writePoolObject(title); + int edgeCount = writeNodes(graph, cfg == null ? null : cfg.getNodeToBlock(), noBlockNodes); + writeEdges(graph, edgeCount); + + + Block[] blocks = cfg == null ? null : cfg.getBlocks(); + writeBlocks(blocks, noBlockNodes, blockToNodes); + flush(); + } + + private void flush() throws IOException { + buffer.flip(); + channel.write(buffer); + buffer.compact(); + } + + private void ensureAvailable(int i) throws IOException { + while (buffer.remaining() < i) { + flush(); + } + } + + private void writeByte(int b) throws IOException { + ensureAvailable(1); + buffer.put((byte) b); + } + + private void writeInt(int b) throws IOException { + ensureAvailable(4); + buffer.putInt(b); + } + + private void writeLong(long b) throws IOException { + ensureAvailable(8); + buffer.putLong(b); + } + + private void writeDouble(double b) throws IOException { + ensureAvailable(8); + buffer.putDouble(b); + } + + private void writeFloat(float b) throws IOException { + ensureAvailable(4); + buffer.putFloat(b); + } + + private void writeShort(char b) throws IOException { + ensureAvailable(2); + buffer.putChar(b); + } + + private void writeString(String str) throws IOException { + writeInt(str.length()); + ensureAvailable(str.length() * 2); + for (int i = 0; i < str.length(); i++) { + buffer.putChar(str.charAt(i)); + } + } + + private void writeBytes(byte[] b) throws IOException { + if (b == null) { + writeInt(-1); + } else { + writeInt(b.length); + ensureAvailable(b.length); + buffer.put(b); + } + } + + private void writeInts(int[] b) throws IOException { + if (b == null) { + writeInt(-1); + } else { + writeInt(b.length); + ensureAvailable(b.length * 4); + for (int i = 0; i < b.length; i++) { + buffer.putInt(b[i]); + } + } + } + + private void writeDoubles(double[] b) throws IOException { + if (b == null) { + writeInt(-1); + } else { + writeInt(b.length); + ensureAvailable(b.length * 8); + for (int i = 0; i < b.length; i++) { + buffer.putDouble(b[i]); + } + } + } + + private void writePoolObject(Object object) throws IOException { + if (object == null) { + writeByte(POOL_NULL); + return; + } + Integer id = constantPool.get(object); + if (id == null) { + addPoolEntry(object); + } else { + if (object instanceof Enum) { + writeByte(POOL_ENUM); + } else if (object instanceof Class) { + writeByte(POOL_CLASS); + } else if (object instanceof ResolvedJavaMethod) { + writeByte(POOL_METHOD); + } else { + writeByte(POOL_STRING); + } + writeInt(id.intValue()); + } + } + + private void addPoolEntry(Object object) throws IOException { + int index = constantPool.add(object); + writeByte(POOL_NEW); + writeInt(index); + if (object instanceof Class) { + Class klass = (Class< ? >) object; + writeByte(POOL_CLASS); + writePoolObject(klass.getName()); + if (klass.isEnum()) { + writeByte(ENUM_KLASS); + Object[] enumConstants = object.getClass().getEnumConstants(); + writeInt(enumConstants.length); + for (Object o : enumConstants) { + writePoolObject(((Enum) o).name()); + } + } else { + writePoolObject(klass.getName()); + writeByte(KLASS); + } + } else if (object instanceof Enum) { + writeByte(POOL_ENUM); + writePoolObject(object.getClass()); + writeInt(((Enum) object).ordinal()); + } else if (object instanceof ResolvedJavaMethod) { + writeByte(POOL_METHOD); + writeBytes(((ResolvedJavaMethod) object).code()); + } else { + writeByte(POOL_STRING); + writeString(object.toString()); + } + } + + private void writePropertyObject(Object obj) throws IOException { + if (obj instanceof Integer) { + writeByte(PROPERTY_INT); + writeInt(((Integer) obj).intValue()); + } else if (obj instanceof Long) { + writeByte(PROPERTY_LONG); + writeLong(((Long) obj).longValue()); + } else if (obj instanceof Double) { + writeByte(PROPERTY_DOUBLE); + writeDouble(((Double) obj).doubleValue()); + } else if (obj instanceof Float) { + writeByte(PROPERTY_FLOAT); + writeFloat(((Float) obj).floatValue()); + } else if (obj instanceof Boolean) { + if (((Boolean) obj).booleanValue()) { + writeByte(PROPERTY_TRUE); + } else { + writeByte(PROPERTY_FALSE); + } + } else if (obj.getClass().isArray()) { + Class< ? > componentType = obj.getClass().getComponentType(); + if (componentType.isPrimitive()) { + if (componentType == Double.TYPE) { + writeByte(PROPERTY_ARRAY); + writeByte(PROPERTY_DOUBLE); + writeDoubles((double[]) obj); + } else if (componentType == Integer.TYPE) { + writeByte(PROPERTY_ARRAY); + writeByte(PROPERTY_DOUBLE); + writeInts((int[]) obj); + } else { + writeByte(PROPERTY_POOL); + writePoolObject(obj); + } + } else { + writeByte(PROPERTY_ARRAY); + writeByte(PROPERTY_POOL); + Object[] array = (Object[]) obj; + writeInt(array.length); + for (Object o : array) { + writePoolObject(o); + } + } + } else { + writeByte(PROPERTY_POOL); + writePoolObject(obj); + } + } + + @SuppressWarnings("deprecation") + private int writeNodes(Graph graph, NodeMap nodeToBlock, Set noBlockNodes) throws IOException { + int edges = 0; + Map props = new HashMap<>(); + writeInt(graph.getNodeCount()); + for (Node node : graph.getNodes()) { + node.getNodeClass().getDebugProperties(node, props); + String name = node.toString(Verbosity.Name); + + writeInt(node.getId()); + writePoolObject(name); + writePoolObject(node.getClass().getSimpleName()); + Block block = nodeToBlock == null ? null : nodeToBlock.get(node); + if (block != null) { + writeInt(block.getId()); + } else { + writeInt(-1); + noBlockNodes.add(node); + } + writeByte(node.predecessor() != null ? 1 : 0); + writeInt(props.size()); + for (Entry entry : props.entrySet()) { + String key = entry.getKey().toString(); + String value = entry.getValue() == null ? "null" : entry.getValue().toString(); + writePoolObject(key); + writePropertyObject(value); + } + edges += node.successors()/*.nonNull()*/.count(); + edges += node.inputs()/*.nonNull()*/.count(); + props.clear(); + } + + return edges; + } + + @SuppressWarnings("deprecation") + private void writeEdges(Graph graph, int edgeCount) throws IOException { + writeInt(edgeCount); + for (Node node : graph.getNodes()) { + // successors + char fromIndex = 0; + NodeClassIterator succIter = node.successors().iterator(); + while (succIter.hasNext()) { + Position position = succIter.nextPosition(); + Node successor = node.getNodeClass().get(node, position); + if (successor != null) { + writeShort(fromIndex); + writeInt(node.getId()); + writeShort((char) 0); + writeInt(successor.getId()); + writePoolObject(node.getNodeClass().getName(position)); + } + fromIndex++; + } + + // inputs + char toIndex = 1; + NodeClassIterator inputIter = node.inputs().iterator(); + while (inputIter.hasNext()) { + Position position = inputIter.nextPosition(); + Node input = node.getNodeClass().get(node, position); + if (input != null) { + writeShort((char) input.successors().count()); + writeInt(input.getId()); + writeShort(toIndex); + writeInt(node.getId()); + writePoolObject(node.getNodeClass().getName(position)); + } + toIndex++; + } + } + } + + @SuppressWarnings("deprecation") + private void writeBlocks(Block[] blocks, Set noBlockNodes, BlockMap> blockToNodes) throws IOException { + if (blocks != null) { + writeInt(blocks.length + (noBlockNodes.isEmpty() ? 0 : 1)); + int suxCount = 0; + for (Block block : blocks) { + List nodes = blockToNodes.get(block); + writeInt(block.getId()); + writeInt(nodes.size()); + for (Node node : nodes) { + writeInt(node.getId()); + } + suxCount += block.getSuccessors().size(); + } + if (!noBlockNodes.isEmpty()) { + writeInt(-1); + writeInt(noBlockNodes.size()); + for (Node node : noBlockNodes) { + writeInt(node.getId()); + } + } + writeInt(suxCount); + for (Block block : blocks) { + for (Block sux : block.getSuccessors()) { + writeInt(block.getId()); + writeInt(sux.getId()); + } + } + } else { + writeInt(0); + } + } + + public void beginGroup(String name, String shortName, ResolvedJavaMethod method, int bci) throws IOException { + writeByte(BEGIN_GROUP); + writePoolObject(name); + writePoolObject(shortName); + writePoolObject(method); + writeInt(bci); + } + + public void endGroup() throws IOException { + writeByte(CLOSE_GROUP); + } +} diff -r cb5fd04e95b3 -r bc237d8b6f99 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinterDumpHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinterDumpHandler.java Mon Jul 09 14:15:55 2012 +0200 @@ -0,0 +1,192 @@ +/* + * 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.graal.printer; + +import java.io.*; +import java.net.*; +import java.nio.channels.*; +import java.util.*; + +import com.oracle.max.criutils.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; + +/** + * Observes compilation events and uses {@link IdealGraphPrinter} to generate a graph representation that can be + * inspected with the Ideal Graph Visualizer. + */ +public class BinaryGraphPrinterDumpHandler implements DebugDumpHandler { + + private static final String DEFAULT_FILE_NAME = "output.gvb"; + + private BinaryGraphPrinter printer; + private List previousInlineContext = new ArrayList<>(); + private String fileName; + private String host; + private int port; + private int failuresCount; + + /** + * Creates a new {@link BinaryGraphPrinterDumpHandler} that writes output to a file named after the compiled method. + */ + public BinaryGraphPrinterDumpHandler() { + this.fileName = DEFAULT_FILE_NAME; + } + + /** + * Creates a new {@link BinaryGraphPrinterDumpHandler} that sends output to a remote IdealGraphVisualizer instance. + */ + public BinaryGraphPrinterDumpHandler(String host, int port) { + this.host = host; + this.port = port; + } + + private void ensureInitialized() { + if (printer == null) { + if (failuresCount > 8) { + return; + } + previousInlineContext.clear(); + if (fileName != null) { + initializeFilePrinter(); + } else { + initializeNetworkPrinter(); + } + } + } + + private void initializeFilePrinter() { + try { + printer = new BinaryGraphPrinter(FileChannel.open(new File(fileName).toPath())); + } catch (IOException e) { + failuresCount++; + printer = null; + } + } + + private void initializeNetworkPrinter() { + try { + SocketChannel channel = SocketChannel.open(new InetSocketAddress(host, port)); + printer = new BinaryGraphPrinter(channel); + TTY.println("Connected to the IGV on port %d", port); + } catch (IOException e) { + TTY.println("Could not connect to the IGV on port %d: %s", port, e); + failuresCount++; + printer = null; + } + } + + @Override + public void dump(Object object, final String message) { + if (object instanceof Graph) { + ensureInitialized(); + if (printer == null) { + return; + } + final Graph graph = (Graph) object; + + if (printer != null) { + // Get all current RiResolvedMethod instances in the context. + List inlineContext = getInlineContext(); + + // Reverse list such that inner method comes after outer method. + Collections.reverse(inlineContext); + + // Check for method scopes that must be closed since the previous dump. + for (int i = 0; i < previousInlineContext.size(); ++i) { + if (i >= inlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) { + for (int j = previousInlineContext.size() - 1; j >= i; --j) { + closeScope(); + } + break; + } + } + + // Check for method scopes that must be opened since the previous dump. + for (int i = 0; i < inlineContext.size(); ++i) { + if (i >= previousInlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) { + for (int j = i; j < inlineContext.size(); ++j) { + openScope(inlineContext.get(j), j == 0); + } + break; + } + } + + // Save inline context for next dump. + previousInlineContext = inlineContext; + + Debug.sandbox("PrintingGraph", new Runnable() { + + @Override + public void run() { + // Finally, output the graph. + try { + printer.print(graph, message, null); + } catch (IOException e) { + failuresCount++; + printer = null; + } + } + }); + } + } + } + + private static List getInlineContext() { + List result = new ArrayList<>(); + for (Object o : Debug.context()) { + if (o instanceof ResolvedJavaMethod) { + ResolvedJavaMethod method = (ResolvedJavaMethod) o; + result.add(MetaUtil.format("%H::%n(%p)", method)); + } else if (o instanceof DebugDumpScope) { + DebugDumpScope debugDumpScope = (DebugDumpScope) o; + if (debugDumpScope.decorator && !result.isEmpty()) { + result.set(result.size() - 1, debugDumpScope.name + ":" + result.get(result.size() - 1)); + } else { + result.add(debugDumpScope.name); + } + } + } + return result; + } + + private void openScope(String name, boolean showThread) { + String prefix = showThread ? Thread.currentThread().getName() + ":" : ""; + try { + printer.beginGroup(prefix + name, name, Debug.contextLookup(ResolvedJavaMethod.class), -1); + } catch (IOException e) { + failuresCount++; + printer = null; + } + } + + private void closeScope() { + try { + printer.endGroup(); + } catch (IOException e) { + failuresCount++; + printer = null; + } + } +} diff -r cb5fd04e95b3 -r bc237d8b6f99 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Wed Jul 04 15:27:28 2012 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Mon Jul 09 14:15:55 2012 +0200 @@ -94,12 +94,12 @@ schedule = new SchedulePhase(); schedule.apply((StructuredGraph) graph); } catch (Throwable t) { - schedule = null; } } + ControlFlowGraph cfg = schedule == null ? null : schedule.getCFG(); beginNodes(); - List edges = printNodes(graph, schedule == null ? null : schedule.getCFG().getNodeToBlock(), noBlockNodes); + List edges = printNodes(graph, cfg == null ? null : cfg.getNodeToBlock(), noBlockNodes); endNodes(); beginEdges(); @@ -108,10 +108,10 @@ } endEdges(); - if (schedule != null) { + if (cfg != null && cfg.getBlocks() != null) { beginControlFlow(); - for (Block block : schedule.getCFG().getBlocks()) { - printBlock(graph, block, schedule.getCFG().getNodeToBlock()); + for (Block block : cfg.getBlocks()) { + printBlock(graph, block, cfg.getNodeToBlock()); } printNoBlock(noBlockNodes); endControlFlow(); diff -r cb5fd04e95b3 -r bc237d8b6f99 src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java --- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java Wed Jul 04 15:27:28 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java Mon Jul 09 14:15:55 2012 +0200 @@ -23,6 +23,7 @@ */ package com.sun.hotspot.igv.coordinator; +import com.sun.hotspot.igv.connection.BinaryServer; import com.sun.hotspot.igv.connection.Server; import com.sun.hotspot.igv.coordinator.actions.*; import com.sun.hotspot.igv.data.GraphDocument; @@ -61,6 +62,7 @@ private GraphDocument document; private FolderNode root; private Server server; + private BinaryServer binaryServer; private OutlineTopComponent() { initComponents(); @@ -116,6 +118,7 @@ }; server = new Server(callback); + binaryServer = new BinaryServer(callback); } public void clear() { diff -r cb5fd04e95b3 -r bc237d8b6f99 src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java Wed Jul 04 15:27:28 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java Mon Jul 09 14:15:55 2012 +0200 @@ -243,10 +243,7 @@ } public void addEdge(InputEdge c) { - // Be tolerant with duplicated edges. - if (!edges.contains(c)) { - edges.add(c); - } + edges.add(c); } public Group getGroup() { diff -r cb5fd04e95b3 -r bc237d8b6f99 src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java Mon Jul 09 14:15:55 2012 +0200 @@ -0,0 +1,447 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.sun.hotspot.igv.data.serialization; + +import com.sun.hotspot.igv.data.*; +import com.sun.hotspot.igv.data.services.GroupCallback; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; +import javax.swing.SwingUtilities; + +/** + * + * @author gd + */ +public class BinaryParser { + private static final int BEGIN_GROUP = 0x00; + private static final int BEGIN_GRAPH = 0x01; + private static final int CLOSE_GROUP = 0x02; + + private static final int POOL_NULL = -1; + private static final int POOL_NEW = 0x00; + private static final int POOL_STRING = 0x01; + private static final int POOL_ENUM = 0x02; + private static final int POOL_CLASS = 0x03; + private static final int POOL_METHOD = 0x04; + + private static final int KLASS = 0x00; + private static final int ENUM_KLASS = 0x01; + + private static final int PROPERTY_POOL = 0x00; + private static final int PROPERTY_INT = 0x01; + private static final int PROPERTY_LONG = 0x02; + private static final int PROPERTY_DOUBLE = 0x03; + private static final int PROPERTY_FLOAT = 0x04; + private static final int PROPERTY_TRUE = 0x05; + private static final int PROPERTY_FALSE = 0x06; + private static final int PROPERTY_ARRAY = 0x07; + + private static final String NO_BLOCK = "noBlock"; + + private GroupCallback callback; + private List constantPool; + private int maxConstant; + private final ByteBuffer buffer; + private final ReadableByteChannel channel; + private Deque folderStack; + + private static class Klass { + public String name; + public Klass(String name) { + this.name = name; + } + } + + private static class EnumKlass extends Klass { + public String[] values; + public EnumKlass(String name, String[] values) { + super(name); + this.values = values; + } + } + + private static class EnumValue { + public EnumKlass enumKlass; + public int ordinal; + public EnumValue(EnumKlass enumKlass, int ordinal) { + this.enumKlass = enumKlass; + this.ordinal = ordinal; + } + } + + public BinaryParser(GroupCallback callback, ReadableByteChannel channel) { + this.callback = callback; + constantPool = new ArrayList<>(); + buffer = ByteBuffer.allocateDirect(64 * 1024); + buffer.flip(); + this.channel = channel; + folderStack = new LinkedList<>(); + } + + private void fill() throws IOException { + buffer.compact(); + channel.read(buffer); + buffer.flip(); + } + + private void ensureAvailable(int i) throws IOException { + while (buffer.remaining() < i) { + fill(); + } + } + + private int readByte() throws IOException { + ensureAvailable(1); + return ((int)buffer.get()) & 0xff; + } + + private int readInt() throws IOException { + ensureAvailable(4); + return buffer.getInt(); + } + + private char readShort() throws IOException { + ensureAvailable(2); + return buffer.getChar(); + } + + private long readLong() throws IOException { + ensureAvailable(8); + return buffer.getLong(); + } + + private double readDouble() throws IOException { + ensureAvailable(8); + return buffer.getDouble(); + } + + private float readFloat() throws IOException { + ensureAvailable(4); + return buffer.getFloat(); + } + + private String readString() throws IOException { + int len = readInt(); + ensureAvailable(len * 2); + char[] chars = new char[len]; + for (int i = 0; i < len; i++) { + chars[i] = buffer.getChar(); + } + return new String(chars); + } + + private byte[] readBytes() throws IOException { + int len = readInt(); + if (len < 0) { + return null; + } + ensureAvailable(len); + byte[] data = new byte[len]; + buffer.get(data); + return data; + } + + private String readIntsToString() throws IOException { + int len = readInt(); + if (len < 0) { + return "null"; + } + ensureAvailable(len * 4); + StringBuilder sb = new StringBuilder().append('['); + for (int i = 0; i < len; i++) { + sb.append(buffer.getInt()); + if (i < len - 1) { + sb.append(", "); + } + } + sb.append(']'); + return sb.toString(); + } + + private String readDoublesToString() throws IOException { + int len = readInt(); + if (len < 0) { + return "null"; + } + ensureAvailable(len * 8); + StringBuilder sb = new StringBuilder().append('['); + for (int i = 0; i < len; i++) { + sb.append(buffer.getDouble()); + if (i < len - 1) { + sb.append(", "); + } + } + sb.append(']'); + return sb.toString(); + } + + private String readPoolObjectsToString() throws IOException { + int len = readInt(); + if (len < 0) { + return "null"; + } + StringBuilder sb = new StringBuilder().append('['); + for (int i = 0; i < len; i++) { + sb.append(readPoolObject(Object.class)); + if (i < len - 1) { + sb.append(", "); + } + } + sb.append(']'); + return sb.toString(); + } + + private T readPoolObject(Class klass) throws IOException { + int type = readByte(); + if (type == POOL_NULL) { + return null; + } + if (type == POOL_NEW) { + return (T) addPoolEntry(klass); + } + int index = readInt(); + if (index < 0 || index >= constantPool.size()) { + throw new IOException("Invalid constant pool index : " + index); + } + Object obj = constantPool.get(index); + return (T) obj; + } + + private boolean assertObjectType(Class klass, int type) { + switch(type) { + case POOL_CLASS: + return klass.isAssignableFrom(Klass.class); + case POOL_ENUM: + return klass.isAssignableFrom(EnumValue.class); + case POOL_METHOD: + return klass.isAssignableFrom(byte[].class); + case POOL_STRING: + return klass.isAssignableFrom(String.class); + case POOL_NULL: + return true; + default: + return false; + } + } + + private Object addPoolEntry(Class klass) throws IOException { + int index = readInt(); + int type = readByte(); + assert assertObjectType(klass, type) : "Wrong object type : " + klass + " != " + type; + Object obj; + switch(type) { + case POOL_CLASS: + String name = readString(); + int klasstype = readByte(); + if (klasstype == ENUM_KLASS) { + int len = readInt(); + String[] values = new String[len]; + for (int i = 0; i < len; i++) { + values[i] = readPoolObject(String.class); + } + obj = new EnumKlass(name, values); + } else if (klasstype == KLASS) { + obj = new Klass(name); + } else { + throw new IOException("unknown klass type"); + } + break; + case POOL_ENUM: + EnumKlass enumClass = readPoolObject(EnumKlass.class); + int ordinal = readInt(); + obj = new EnumValue(enumClass, ordinal); + break; + case POOL_METHOD: + obj = readBytes(); + break; + case POOL_STRING: + obj = readString(); + break; + default: + throw new IOException("unknown pool type"); + } + while (constantPool.size() <= index) { + constantPool.add(null); + } + constantPool.set(index, obj); + return obj; + } + + private Object readPropertyObject() throws IOException { + int type = readByte(); + switch (type) { + case PROPERTY_INT: + return readInt(); + case PROPERTY_LONG: + return readLong(); + case PROPERTY_FLOAT: + return readFloat(); + case PROPERTY_DOUBLE: + return readDouble(); + case PROPERTY_TRUE: + return Boolean.TRUE; + case PROPERTY_FALSE: + return Boolean.FALSE; + case PROPERTY_POOL: + return readPoolObject(Object.class); + case PROPERTY_ARRAY: + int subType = readByte(); + switch(subType) { + case PROPERTY_INT: + return readIntsToString(); + case PROPERTY_DOUBLE: + return readDoublesToString(); + case PROPERTY_POOL: + return readPoolObjectsToString(); + default: + throw new IOException("Unknown type"); + } + default: + throw new IOException("Unknown type"); + } + } + + public void parse() throws IOException { + folderStack.push(new GraphDocument()); + while(true) { + parseRoot(); + } + } + + private void parseRoot() throws IOException { + int type = readByte(); + switch(type) { + case BEGIN_GRAPH: { + final Folder parent = folderStack.peek(); + final InputGraph graph = parseGraph(); + SwingUtilities.invokeLater(new Runnable(){ + @Override + public void run() { + parent.addElement(graph); + } + }); + break; + } + case BEGIN_GROUP: { + final Folder parent = folderStack.peek(); + final Group group = parseGroup(parent); + if (callback == null || parent instanceof Group) { + SwingUtilities.invokeLater(new Runnable(){ + @Override + public void run() { + parent.addElement(group); + } + }); + } + folderStack.push(group); + if (callback != null && parent instanceof GraphDocument) { + callback.started(group); + } + break; + } + case CLOSE_GROUP: { + if (folderStack.isEmpty()) { + throw new IOException("Unbalanced groups"); + } + folderStack.pop(); + break; + } + default: + throw new IOException("unknown root : " + type); + } + } + + private Group parseGroup(Folder parent) throws IOException { + String name = readPoolObject(String.class); + String shortName = readPoolObject(String.class); + byte[] bytecodes = readPoolObject(byte[].class); + int bci = readInt(); + Group group = new Group(parent); + group.getProperties().setProperty("name", name); + final InputMethod method = new InputMethod(group, name, shortName, bci); + if (bytecodes != null) { + method.setBytecodes("TODO"); + } + group.setMethod(method); + return group; + } + + private InputGraph parseGraph() throws IOException { + String title = readPoolObject(String.class); + InputGraph graph = new InputGraph(title); + parseNodes(graph); + parseEdges(graph); + parseBlocks(graph); + graph.ensureNodesInBlocks(); + return graph; + } + + private void parseBlocks(InputGraph graph) throws IOException { + int blockCount = readInt(); + for (int i = 0; i < blockCount; i++) { + int id = readInt(); + String name = id >= 0 ? Integer.toString(id) : NO_BLOCK; + InputBlock block = graph.addBlock(name); + int nodeCount = readInt(); + for (int j = 0; j < nodeCount; j++) { + block.addNode(readInt()); + } + } + int edgeCount = readInt(); + for (int i = 0; i < edgeCount; i++) { + int from = readInt(); + int to = readInt(); + String fromName = from >= 0 ? Integer.toString(from) : NO_BLOCK; + String toName = to >= 0 ? Integer.toString(to) : NO_BLOCK; + graph.addBlockEdge(graph.getBlock(fromName), graph.getBlock(toName)); + } + } + + private void parseEdges(InputGraph graph) throws IOException { + int count = readInt(); + for (int i = 0; i < count; i++) { + char fromIndex = readShort(); + int from = readInt(); + char toIndex = readShort(); + int to = readInt(); + String label = readPoolObject(String.class); + graph.addEdge(new InputEdge(fromIndex, toIndex, from, to, label)); + } + } + + private void parseNodes(InputGraph graph) throws IOException { + int count = readInt(); + + for (int i = 0; i < count; i++) { + int id = readInt(); + InputNode node = new InputNode(id); + final Properties properties = node.getProperties(); + String name = readPoolObject(String.class); + String simpleName = readPoolObject(String.class); + int block = readInt(); + int preds = readByte(); + properties.setProperty("name", name); + properties.setProperty("class", simpleName); + properties.setProperty("predecessorCount", Integer.toString(preds)); + if (block > 0) { + properties.setProperty("block", Integer.toString(block)); + } else { + properties.setProperty("block", NO_BLOCK); + } + int propCount = readInt(); + for (int j = 0; j < propCount; j++) { + String key = readPoolObject(String.class); + Object value = readPropertyObject(); + properties.setProperty(key, value.toString()); + } + graph.addNode(node); + } + } +} diff -r cb5fd04e95b3 -r bc237d8b6f99 src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/BinaryClient.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/BinaryClient.java Mon Jul 09 14:15:55 2012 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1998, 2007, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.hotspot.igv.connection; + +import com.sun.hotspot.igv.data.serialization.BinaryParser; +import com.sun.hotspot.igv.data.services.GroupCallback; +import java.io.IOException; +import java.nio.channels.SocketChannel; +import org.openide.util.Exceptions; + +/** + * + * @author Thomas Wuerthinger + */ +public class BinaryClient implements Runnable { + + private SocketChannel socket; + private GroupCallback callback; + + public BinaryClient(SocketChannel socket, GroupCallback callback) { + this.callback = callback; + this.socket = socket; + } + + @Override + public void run() { + + try { + final SocketChannel channel = socket; + channel.configureBlocking(true); + new BinaryParser(callback, channel).parse(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } finally { + try { + socket.close(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + } +} \ No newline at end of file diff -r cb5fd04e95b3 -r bc237d8b6f99 src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/BinaryServer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/BinaryServer.java Mon Jul 09 14:15:55 2012 +0200 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1998, 2007, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.hotspot.igv.connection; + +import com.sun.hotspot.igv.data.services.GroupCallback; +import com.sun.hotspot.igv.settings.Settings; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketAddress; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.prefs.PreferenceChangeEvent; +import java.util.prefs.PreferenceChangeListener; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.util.RequestProcessor; + +/** + * + * @author Thomas Wuerthinger + */ +public class BinaryServer implements PreferenceChangeListener { + + private ServerSocketChannel serverSocket; + private GroupCallback callback; + private int port; + private Runnable serverRunnable; + + public BinaryServer(GroupCallback callback) { + + this.callback = callback; + initializeNetwork(); + Settings.get().addPreferenceChangeListener(this); + } + + @Override + public void preferenceChange(PreferenceChangeEvent e) { + + int curPort = Integer.parseInt(Settings.get().get(Settings.PORT_BINARY, Settings.PORT_BINARY_DEFAULT)); + if (curPort != port) { + initializeNetwork(); + } + } + + private void initializeNetwork() { + + int curPort = Integer.parseInt(Settings.get().get(Settings.PORT_BINARY, Settings.PORT_BINARY_DEFAULT)); + this.port = curPort; + try { + serverSocket = ServerSocketChannel.open(); + serverSocket.bind(new InetSocketAddress(curPort)); + } catch (IOException ex) { + NotifyDescriptor message = new NotifyDescriptor.Message("Could not create server. Listening for incoming binary data is disabled.", NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notifyLater(message); + return; + } + + Runnable runnable = new Runnable() { + + @Override + public void run() { + while (true) { + try { + SocketChannel clientSocket = serverSocket.accept(); + if (serverRunnable != this) { + clientSocket.close(); + return; + } + RequestProcessor.getDefault().post(new BinaryClient(clientSocket, callback), 0, Thread.MAX_PRIORITY); + } catch (IOException ex) { + serverSocket = null; + NotifyDescriptor message = new NotifyDescriptor.Message("Error during listening for incoming connections. Listening for incoming binary data is disabled.", NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notifyLater(message); + return; + } + } + } + }; + + serverRunnable = runnable; + + RequestProcessor.getDefault().post(runnable, 0, Thread.MAX_PRIORITY); + } +} diff -r cb5fd04e95b3 -r bc237d8b6f99 src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/Settings.java --- a/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/Settings.java Wed Jul 04 15:27:28 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/Settings.java Mon Jul 09 14:15:55 2012 +0200 @@ -37,7 +37,9 @@ public final static String NODE_WIDTH = "nodeWidth"; public final static String NODE_WIDTH_DEFAULT = "100"; public final static String PORT = "port"; + public final static String PORT_BINARY = "portBinary"; public final static String PORT_DEFAULT = "4444"; + public final static String PORT_BINARY_DEFAULT = "4445"; public final static String DIRECTORY = "directory"; public final static String DIRECTORY_DEFAULT = System.getProperty("user.dir");