changeset 5813:3b8bc07f8d17

Add ability to give an existing to getDebugProperties Add nameTemplate to NodeInfo, use it in binary graphs improve binary graph protocol (transmit NodeClass through the constant pool including nameTemplate and edges names, transmit edges as part of nodes and blocks)
author Gilles Duboscq <duboscq@ssw.jku.at>
date Tue, 10 Jul 2012 15:02:41 +0200
parents 32613b375b30
children d241f8b2e6f9
files graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInfo.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/RegisterNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java
diffstat 21 files changed, 290 insertions(+), 212 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Jul 10 15:02:41 2012 +0200
@@ -416,12 +416,21 @@
 
     /**
      * Provides a {@link Map} of properties of this node for use in debugging (e.g., to view in the ideal graph
-     * visualizer). Subclasses overriding this method should add to the map returned by their superclass.
+     * visualizer).
      */
     public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> map = new HashMap<>();
+        return getDebugProperties(new HashMap<>());
+    }
+
+
+    /**
+     * Fills a {@link Map} with properties of this node for use in debugging (e.g., to view in the ideal graph
+     * visualizer). Subclasses overriding this method should also fill the map using their superclass.
+     * @param map
+     */
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
         map.put("usageCount", usages.size());
-        map.put("predecessorCount", predecessor == null ? 0 : 1);
+        map.put("hasPredecessor", predecessor != null);
         getNodeClass().getDebugProperties(this, map);
         return map;
     }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Jul 10 15:02:41 2012 +0200
@@ -28,6 +28,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
+import com.oracle.graal.graph.Node.*;
 
 import sun.misc.Unsafe;
 
@@ -83,6 +84,7 @@
     private final boolean canGVN;
     private final int startGVNNumber;
     private final String shortName;
+    private final String nameTemplate;
     private final int iterableId;
     private final boolean hasOutgoingEdges;
 
@@ -122,12 +124,17 @@
         if (newShortName.endsWith("Node") && !newShortName.equals("StartNode") && !newShortName.equals("EndNode")) {
             newShortName = newShortName.substring(0, newShortName.length() - 4);
         }
+        String newNameTemplate = null;
         NodeInfo info = clazz.getAnnotation(NodeInfo.class);
         if (info != null) {
             if (!info.shortName().isEmpty()) {
                 newShortName = info.shortName();
             }
+            if (!info.nameTemplate().isEmpty()) {
+                newNameTemplate = info.nameTemplate();
+            }
         }
+        this.nameTemplate = newNameTemplate == null ? newShortName : newNameTemplate;
         this.shortName = newShortName;
         if (Node.IterableNodeType.class.isAssignableFrom(clazz)) {
             this.iterableId = nextIterableId++;
@@ -570,8 +577,10 @@
                 } else {
                     assert false : "unhandled property type: " + type;
                 }
+            } else {
+                value = unsafe.getObject(node, dataOffsets[i]);
             }
-            properties.put("data." + dataNames[i], value);
+            properties.put(dataNames[i], value);
         }
     }
 
@@ -898,12 +907,32 @@
         return false;
     }
 
-    public int directInputCount() {
-        return directInputCount;
+    public List<Position> getFirstLevelInputPositions() {
+        List<Position> positions = new ArrayList<>(inputOffsets.length);
+        for (int i = 0; i < inputOffsets.length; i++) {
+            positions.add(new Position(true, i, NOT_ITERABLE));
+        }
+        return positions;
     }
 
-    public int directSuccessorCount() {
-        return directSuccessorCount;
+    public List<Position> getFirstLevelSuccessorPositions() {
+        List<Position> positions = new ArrayList<>(successorOffsets.length);
+        for (int i = 0; i < successorOffsets.length; i++) {
+            positions.add(new Position(false, i, NOT_ITERABLE));
+        }
+        return positions;
+    }
+
+    public Class<?> getJavaClass() {
+        return clazz;
+    }
+
+    /**
+     * The template used to build the {@link Verbosity#Name} version.
+     * Variable part are specified using &#123;i#inputName&#125; or &#123;p#propertyName&#125;.
+     */
+    public String getNameTemplate() {
+        return nameTemplate;
     }
 
     static Map<Node, Node> addGraphDuplicate(Graph graph, Iterable<Node> nodes, DuplicationReplacement replacements) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInfo.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInfo.java	Tue Jul 10 15:02:41 2012 +0200
@@ -27,9 +27,16 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
+import com.oracle.graal.graph.Node.*;
+
 
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.TYPE)
 public @interface NodeInfo {
     String shortName() default "";
+    /**
+     * The template used to build the {@link Verbosity#Name} version.
+     * Variable part are specified using &#123;i#inputName&#125; or &#123;p#propertyName&#125;.
+     */
+    String nameTemplate() default "";
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/RegisterNode.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/RegisterNode.java	Tue Jul 10 15:02:41 2012 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -33,6 +34,7 @@
 /**
  * Access the value of a specific register.
  */
+@NodeInfo(nameTemplate = "Register %{p#register}")
 public final class RegisterNode extends FixedWithNextNode implements LIRLowerable {
 
     private final Register register;
@@ -65,13 +67,6 @@
         }
     }
 
-    @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> properties = super.getDebugProperties();
-        properties.put("register", register.toString());
-        return properties;
-    }
-
     @SuppressWarnings("unused")
     @NodeIntrinsic
     public static <T> T register(@ConstantNodeParameter Register register, @ConstantNodeParameter Kind kind) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java	Tue Jul 10 15:02:41 2012 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import java.util.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -70,13 +68,6 @@
         tool.getRuntime().lower(this, tool);
     }
 
-    @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> debugProperties = super.getDebugProperties();
-        debugProperties.put("size", String.valueOf(size));
-        return debugProperties;
-    }
-
     /**
      * @return null if allocation fails
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Tue Jul 10 15:02:41 2012 +0200
@@ -62,8 +62,8 @@
     }
 
     @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> debugProperties = super.getDebugProperties();
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
+        Map<Object, Object> debugProperties = super.getDebugProperties(map);
         debugProperties.put("shortName", "B");
         return debugProperties;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Tue Jul 10 15:02:41 2012 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
@@ -32,7 +34,7 @@
  * The {@code ConstantNode} represents a constant such as an integer value,
  * long, float, object reference, address, etc.
  */
-@NodeInfo(shortName = "Const")
+@NodeInfo(shortName = "Const", nameTemplate = "Const({p#rawvalue})")
 public class ConstantNode extends BooleanNode implements LIRLowerable {
 
     public final Constant value;
@@ -219,6 +221,13 @@
     }
 
     @Override
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
+        Map<Object, Object> properties = super.getDebugProperties(map);
+        properties.put("rawvalue", value.kind.isObject() ? value.kind.format(value.boxedValue()) : value.boxedValue());
+        return properties;
+    }
+
+    @Override
     public String toString(Verbosity verbosity) {
         if (verbosity == Verbosity.Name) {
             return super.toString(Verbosity.Name) + "(" + value.kind.format(value.boxedValue()) + ")";
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Tue Jul 10 15:02:41 2012 +0200
@@ -85,17 +85,6 @@
         };
     }
 
-    @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> properties = super.getDebugProperties();
-        StringBuilder str = new StringBuilder();
-        for (int i = 0; i < branchProbability.length; i++) {
-            str.append(i == 0 ? "" : ", ").append(String.format(Locale.ENGLISH, "%7.5f", branchProbability[i]));
-        }
-        properties.put("branchProbability", str.toString());
-        return properties;
-    }
-
     public int blockSuccessorIndex(BeginNode successor) {
         int idx = blockSuccessors.indexOf(successor);
         if (idx < 0) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java	Tue Jul 10 15:02:41 2012 +0200
@@ -50,13 +50,6 @@
     }
 
     @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> debugProperties = super.getDebugProperties();
-        debugProperties.put("shortName", "E");
-        return debugProperties;
-    }
-
-    @Override
     public Iterable< ? extends Node> cfgSuccessors() {
         return Arrays.asList(merge());
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Tue Jul 10 15:02:41 2012 +0200
@@ -352,9 +352,8 @@
     }
 
     @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> properties = super.getDebugProperties();
-        properties.put("bci", bci);
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
+        Map<Object, Object> properties = super.getDebugProperties(map);
         if (method != null) {
             properties.put("method", MetaUtil.format("%H.%n(%p):%r", method));
             StackTraceElement ste = method.toStackTraceElement(bci);
@@ -374,8 +373,6 @@
             sb.append(i == 0 ? "" : ", ").append(stackAt(i) == null ? "_" : stackAt(i).toString(Verbosity.Id));
         }
         properties.put("stack", sb.toString());
-        properties.put("rethrowException", rethrowException);
-        properties.put("duringCall", duringCall);
         return properties;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Tue Jul 10 15:02:41 2012 +0200
@@ -34,6 +34,7 @@
 /**
  * The {@code InvokeNode} represents all kinds of method calls.
  */
+@NodeInfo(nameTemplate = "Invoke#{p#targetMethod}")
 public final class InvokeNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, Invoke, LIRLowerable, MemoryCheckpoint  {
 
     @Input private final MethodCallTargetNode callTarget;
@@ -86,8 +87,8 @@
     }
 
     @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> debugProperties = super.getDebugProperties();
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
+        Map<Object, Object> debugProperties = super.getDebugProperties(map);
         if (callTarget != null && callTarget.targetMethod() != null) {
             debugProperties.put("targetMethod", MetaUtil.format("%h.%n(%p)", callTarget.targetMethod()));
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Jul 10 15:02:41 2012 +0200
@@ -30,7 +30,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
-
+@NodeInfo(nameTemplate = "Invoke!#{p#targetMethod}")
 public class InvokeWithExceptionNode extends ControlSplitNode implements Node.IterableNodeType, Invoke, MemoryCheckpoint, LIRLowerable {
     public static final int NORMAL_EDGE = 0;
     public static final int EXCEPTION_EDGE = 1;
@@ -152,8 +152,8 @@
     }
 
     @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> debugProperties = super.getDebugProperties();
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
+        Map<Object, Object> debugProperties = super.getDebugProperties(map);
         debugProperties.put("memoryCheckpoint", "true");
         if (callTarget != null && callTarget.targetMethod() != null) {
             debugProperties.put("targetMethod", MetaUtil.format("%h.%n(%p)", callTarget.targetMethod()));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Tue Jul 10 15:02:41 2012 +0200
@@ -140,13 +140,6 @@
         return super.verify();
     }
 
-    @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> properties = super.getDebugProperties();
-        properties.put("loopFrequency", String.format("%7.1f", loopFrequency));
-        return properties;
-    }
-
     public int nextEndIndex() {
         return nextEndIndex++;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Tue Jul 10 15:02:41 2012 +0200
@@ -32,6 +32,7 @@
  * The {@code PhiNode} represents the merging of dataflow in the graph. It refers to a merge
  * and a variable.
  */
+@NodeInfo(nameTemplate = "Phi({i#values})")
 public final class PhiNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType {
 
     public static enum PhiType {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java	Tue Jul 10 15:02:41 2012 +0200
@@ -40,8 +40,8 @@
     }
 
     @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> debugProperties = super.getDebugProperties();
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
+        Map<Object, Object> debugProperties = super.getDebugProperties(map);
         if (this instanceof StateSplit) {
             StateSplit stateSplit = (StateSplit) this;
             if (stateSplit.stateAfter() != null) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Tue Jul 10 15:02:41 2012 +0200
@@ -180,8 +180,8 @@
     }
 
     @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> properties = super.getDebugProperties();
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
+        Map<Object, Object> properties = super.getDebugProperties(map);
         if (!dependencies.isEmpty()) {
             StringBuilder str = new StringBuilder();
             for (int i = 0; i < dependencies.size(); i++) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Tue Jul 10 15:02:41 2012 +0200
@@ -91,8 +91,8 @@
     }
 
     @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> debugProperties = super.getDebugProperties();
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
+        Map<Object, Object> debugProperties = super.getDebugProperties(map);
         debugProperties.put("field", MetaUtil.format("%h.%n", field));
         return debugProperties;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Tue Jul 10 15:02:41 2012 +0200
@@ -65,13 +65,6 @@
         gen.visitNewInstance(this);
     }
 
-    @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> properties = super.getDebugProperties();
-        properties.put("instanceClass", instanceClass);
-        return properties;
-    }
-
     public EscapeOp getEscapeOp() {
         return ESCAPE;
     }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Tue Jul 10 15:02:41 2012 +0200
@@ -31,7 +31,6 @@
 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.*;
@@ -44,12 +43,13 @@
     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 POOL_NULL = 0x05;
+    private static final int POOL_NODE_CLASS = 0x06;
 
     private static final int PROPERTY_POOL = 0x00;
     private static final int PROPERTY_INT = 0x01;
@@ -95,20 +95,21 @@
     }
 
     private final CosntantPool constantPool;
-
-
     private final ByteBuffer buffer;
     private final WritableByteChannel channel;
-
+    private long bytes;
+    private long newPoolEntry;
 
     public BinaryGraphPrinter(WritableByteChannel channel) {
         constantPool = new CosntantPool();
-        buffer = ByteBuffer.allocateDirect(64 * 1024);
+        buffer = ByteBuffer.allocateDirect(256 * 1024);
         this.channel = channel;
     }
 
     public void print(Graph graph, String title, SchedulePhase predefinedSchedule) throws IOException {
-        Set<Node> noBlockNodes = new HashSet<>();
+        long startBytes = bytes;
+        long startTime = System.currentTimeMillis();
+        long startPool = newPoolEntry;
         SchedulePhase schedule = predefinedSchedule;
         if (schedule == null) {
             try {
@@ -118,22 +119,22 @@
             }
         }
         ControlFlowGraph cfg =  schedule == null ? null : schedule.getCFG();
-
         BlockMap<List<ScheduledNode>> blockToNodes = schedule == null ? null : schedule.getBlockToNodesMap();
+        Block[] blocks = cfg == null ? null : cfg.getBlocks();
         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);
+        writeNodes(graph);
+        writeBlocks(blocks, blockToNodes);
         flush();
+        long t = System.currentTimeMillis() - startTime;
+        long b = bytes - startBytes;
+        long pool = newPoolEntry - startPool;
+        System.out.println("Graph printed in " + t + " ms and " + b + " bytes, " + pool + " pool entries created (" + graph.getNodeCount() + " nodes)");
     }
 
     private void flush() throws IOException {
         buffer.flip();
-        channel.write(buffer);
+        bytes += channel.write(buffer);
         buffer.compact();
     }
 
@@ -228,6 +229,8 @@
                 writeByte(POOL_ENUM);
             } else if (object instanceof Class<?>) {
                 writeByte(POOL_CLASS);
+            } else if (object instanceof NodeClass) {
+                writeByte(POOL_NODE_CLASS);
             } else if (object instanceof ResolvedJavaMethod) {
                 writeByte(POOL_METHOD);
             } else {
@@ -238,28 +241,43 @@
     }
 
     private void addPoolEntry(Object object) throws IOException {
+        newPoolEntry++;
         int index = constantPool.add(object);
         writeByte(POOL_NEW);
         writeInt(index);
         if (object instanceof Class<?>) {
             Class<?> klass = (Class< ? >) object;
             writeByte(POOL_CLASS);
-            writePoolObject(klass.getName());
+            writeString(klass.getName());
             if (klass.isEnum()) {
                 writeByte(ENUM_KLASS);
-                Object[] enumConstants = object.getClass().getEnumConstants();
+                Object[] enumConstants = klass.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 NodeClass) {
+            NodeClass nodeClass = (NodeClass) object;
+            writeByte(POOL_NODE_CLASS);
+            writeString(nodeClass.getJavaClass().getSimpleName());
+            writeString(nodeClass.getNameTemplate());
+            List<Position> directInputPositions = nodeClass.getFirstLevelInputPositions();
+            writeShort((char) directInputPositions.size());
+            for (Position pos : directInputPositions) {
+                writePoolObject(nodeClass.getName(pos));
+            }
+            List<Position> directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions();
+            writeShort((char) directSuccessorPositions.size());
+            for (Position pos : directSuccessorPositions) {
+                writePoolObject(nodeClass.getName(pos));
+            }
         } else if (object instanceof ResolvedJavaMethod) {
             writeByte(POOL_METHOD);
             writeBytes(((ResolvedJavaMethod) object).code());
@@ -288,7 +306,7 @@
             } else {
                 writeByte(PROPERTY_FALSE);
             }
-        } else if (obj.getClass().isArray()) {
+        } else if (obj != null && obj.getClass().isArray()) {
             Class< ? > componentType = obj.getClass().getComponentType();
             if (componentType.isPrimitive()) {
                 if (componentType == Double.TYPE) {
@@ -297,7 +315,7 @@
                     writeDoubles((double[]) obj);
                 } else if (componentType == Integer.TYPE) {
                     writeByte(PROPERTY_ARRAY);
-                    writeByte(PROPERTY_DOUBLE);
+                    writeByte(PROPERTY_INT);
                     writeInts((int[]) obj);
                 } else {
                     writeByte(PROPERTY_POOL);
@@ -319,83 +337,48 @@
     }
 
     @SuppressWarnings("deprecation")
-    private int writeNodes(Graph graph, NodeMap<Block> nodeToBlock, Set<Node> noBlockNodes) throws IOException {
-        int edges = 0;
+    private void writeNodes(Graph graph) throws IOException {
         Map<Object, Object> props = new HashMap<>();
         writeInt(graph.getNodeCount());
         for (Node node : graph.getNodes()) {
-            node.getNodeClass().getDebugProperties(node, props);
-            String name = node.toString(Verbosity.Name);
-
+            NodeClass nodeClass = node.getNodeClass();
+            node.getDebugProperties(props);
             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());
+            writePoolObject(nodeClass);
+            writeShort((char) props.size());
             for (Entry<Object, Object> entry : props.entrySet()) {
                 String key = entry.getKey().toString();
-                String value = entry.getValue() == null ? "null" : entry.getValue().toString();
                 writePoolObject(key);
-                writePropertyObject(value);
+                writePropertyObject(entry.getValue());
             }
-            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++;
+            NodeSuccessorsIterable successors = node.successors();
+            writeShort((char) successors.count());
+            NodeClassIterator suxIt = successors.iterator();
+            while (suxIt.hasNext()) {
+                Position pos = suxIt.nextPosition();
+                Node sux = nodeClass.get(node, pos);
+                writeInt(sux.getId());
+                writeShort((char) pos.index);
             }
-
-            // 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++;
+            //inputs
+            NodeInputsIterable inputs = node.inputs();
+            writeShort((char) inputs.count());
+            NodeClassIterator inIt = inputs.iterator();
+            while (inIt.hasNext()) {
+                Position pos = inIt.nextPosition();
+                Node in = nodeClass.get(node, pos);
+                writeInt(in.getId());
+                writeShort((char) pos.index);
             }
+            props.clear();
         }
     }
 
     @SuppressWarnings("deprecation")
-    private void writeBlocks(Block[] blocks, Set<Node> noBlockNodes, BlockMap<List<ScheduledNode>> blockToNodes) throws IOException {
+    private void writeBlocks(Block[] blocks, BlockMap<List<ScheduledNode>> blockToNodes) throws IOException {
         if (blocks != null) {
-            writeInt(blocks.length + (noBlockNodes.isEmpty() ? 0 : 1));
-            int suxCount = 0;
+            writeInt(blocks.length);
             for (Block block : blocks) {
                 List<ScheduledNode> nodes = blockToNodes.get(block);
                 writeInt(block.getId());
@@ -403,19 +386,8 @@
                 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) {
+                writeInt(block.getSuccessors().size());
                 for (Block sux : block.getSuccessors()) {
-                    writeInt(block.getId());
                     writeInt(sux.getId());
                 }
             }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java	Tue Jul 10 15:02:41 2012 +0200
@@ -6,6 +6,7 @@
 
 import com.sun.hotspot.igv.data.*;
 import com.sun.hotspot.igv.data.services.GroupCallback;
+import java.io.EOFException;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.channels.ReadableByteChannel;
@@ -13,6 +14,8 @@
 import java.util.Deque;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import javax.swing.SwingUtilities;
 
 /**
@@ -24,12 +27,13 @@
     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 POOL_NULL = 0x05;
+    private static final int POOL_NODE_CLASS = 0x06;
     
     private static final int KLASS = 0x00;
     private static final int ENUM_KLASS = 0x01;
@@ -51,6 +55,7 @@
     private final ByteBuffer buffer;
     private final ReadableByteChannel channel;
     private Deque<Folder> folderStack;
+    private boolean close;
     
     private static class Klass {
         public String name;
@@ -67,6 +72,19 @@
         }
     }
     
+    private static class NodeClass {
+        public final String className;
+        public final String nameTemplate;
+        public final List<String> inputs;
+        public final List<String> sux;
+        private NodeClass(String className, String nameTemplate, List<String> inputs, List<String> sux) {
+            this.className = className;
+            this.nameTemplate = nameTemplate;
+            this.inputs = inputs;
+            this.sux = sux;
+        }
+    }
+    
     private static class EnumValue {
         public EnumKlass enumKlass;
         public int ordinal;
@@ -79,7 +97,7 @@
     public BinaryParser(GroupCallback callback, ReadableByteChannel channel) {
         this.callback = callback;
         constantPool = new ArrayList<>();
-        buffer = ByteBuffer.allocateDirect(64 * 1024);
+        buffer = ByteBuffer.allocateDirect(256 * 1024);
         buffer.flip();
         this.channel = channel;
         folderStack = new LinkedList<>();
@@ -87,7 +105,9 @@
     
     private void fill() throws IOException {
         buffer.compact();
-        channel.read(buffer);
+        if (channel.read(buffer) < 0) {
+            throw new EOFException();
+        }
         buffer.flip();
     }
     
@@ -217,13 +237,15 @@
     private boolean assertObjectType(Class<?> klass, int type) {
         switch(type) {
             case POOL_CLASS:
-                return klass.isAssignableFrom(Klass.class);
+                return klass.isAssignableFrom(EnumKlass.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_NODE_CLASS:
+                return klass.isAssignableFrom(NodeClass.class);
             case POOL_NULL:
                 return true;
             default:
@@ -250,7 +272,7 @@
                 } else if (klasstype == KLASS) {
                     obj = new Klass(name);
                 } else {
-                    throw new IOException("unknown klass type");
+                    throw new IOException("unknown klass type : " + klasstype);
                 }
                 break;
             case POOL_ENUM:
@@ -258,6 +280,21 @@
                 int ordinal = readInt();
                 obj = new EnumValue(enumClass, ordinal);
                 break;
+            case POOL_NODE_CLASS:
+                String className = readString();
+                String nameTemplate = readString();
+                int inputCount = readShort();
+                List<String> inputs = new ArrayList<>(inputCount);
+                for (int i = 0; i < inputCount; i++) {
+                    inputs.add(readPoolObject(String.class));
+                }
+                int suxCount = readShort();
+                List<String> sux = new ArrayList<>(suxCount);
+                for (int i = 0; i < suxCount; i++) {
+                    sux.add(readPoolObject(String.class));
+                }
+                obj = new NodeClass(className, nameTemplate, inputs, sux);
+                break;
             case POOL_METHOD:
                 obj = readBytes();
                 break;
@@ -310,8 +347,12 @@
 
     public void parse() throws IOException {
         folderStack.push(new GraphDocument());
-        while(true) {
-            parseRoot();
+        try {
+            while(true) {
+                parseRoot();
+            }
+        } catch (EOFException e) {
+            
         }
     }
 
@@ -377,7 +418,6 @@
         String title = readPoolObject(String.class);
         InputGraph graph = new InputGraph(title);
         parseNodes(graph);
-        parseEdges(graph);
         parseBlocks(graph);
         graph.ensureNodesInBlocks();
         return graph;
@@ -385,63 +425,122 @@
     
     private void parseBlocks(InputGraph graph) throws IOException {
         int blockCount = readInt();
+        List<Edge> edges = new LinkedList<>();
         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 nodeId = readInt();
+                block.addNode(nodeId);
+                graph.getNode(nodeId).getProperties().setProperty("block", name);
+            }
+            int edgeCount = readInt();
+            for (int j = 0; j < edgeCount; j++) {
+                int to = readInt();
+                edges.add(new Edge(id, to));
             }
         }
-        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;
+        for (Edge e : edges) {
+            String fromName = e.from >= 0 ? Integer.toString(e.from) : NO_BLOCK;
+            String toName = e.to >= 0 ? Integer.toString(e.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();
-        
+        List<Edge> edges = new LinkedList<>();
         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();
+            NodeClass nodeClass = readPoolObject(NodeClass.class);
+            int propCount = readShort();
             for (int j = 0; j < propCount; j++) {
                 String key = readPoolObject(String.class);
                 Object value = readPropertyObject();
-                properties.setProperty(key, value.toString());
+                properties.setProperty(key, value != null ? value.toString() : "null");
+            }
+            int edgesStart = edges.size();
+            int suxCount = readShort();
+            for (int j = 0; j < suxCount; j++) {
+                int sux = readInt();
+                int index = readShort();
+                edges.add(new Edge(id, sux, (char) j, nodeClass.sux.get(index), false));
+            }
+            int inputCount = readShort();
+            for (int j = 0; j < inputCount; j++) {
+                int in = readInt();
+                int index = readShort();
+                edges.add(new Edge(in, id, (char) j, nodeClass.inputs.get(index), true));
             }
+            properties.setProperty("name", createName(edges.subList(edgesStart, edges.size()), properties, nodeClass.nameTemplate));
+            properties.setProperty("class", nodeClass.className);
             graph.addNode(node);
         }
+        for (Edge e : edges) {
+            char fromIndex = e.input ? 0 : e.num;
+            char toIndex = e.input ? e.num : 0;
+            graph.addEdge(new InputEdge(fromIndex, toIndex, e.from, e.to, e.label));
+        }
+    }
+    
+    private String createName(List<Edge> edges, Properties properties, String template) {
+        Pattern p = Pattern.compile("\\{(p|i)#(.+)\\}");
+        Matcher m = p.matcher(template);
+        StringBuffer sb = new StringBuffer();
+        while (m.find()) {
+            String name = m.group(2);
+            String type = m.group(1);
+            String result;
+            switch (type) {
+                case "i":
+                    StringBuilder inputString = new StringBuilder();
+                    for(Edge edge : edges) {
+                        if (name.equals(edge.label)) {
+                            if (inputString.length() > 0) {
+                                inputString.append(", ");
+                            }
+                            inputString.append(edge.from);
+                        }
+                    }
+                    result = inputString.toString();
+                    break;
+                case "p":
+                    result = properties.get(name);
+                    if (result == null) {
+                        result = "?";
+                    }
+                    break;
+                default:
+                    result = "#?#";
+                    break;
+            }
+            result = result.replace("\\", "\\\\");
+            result = result.replace("$", "\\$");
+            m.appendReplacement(sb, result);
+        }
+        m.appendTail(sb);
+        return sb.toString();
+    }
+    
+    private static class Edge {
+        final int from;
+        final int to;
+        final char num;
+        final String label;
+        final boolean input;
+        public Edge(int from, int to) {
+            this(from, to, (char) 0, null, false);
+        }
+        public Edge(int from, int to, char num, String label, boolean input) {
+            this.from = from;
+            this.to = to;
+            this.label = label;
+            this.num = num;
+            this.input = input;
+        }
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java	Mon Jul 09 15:30:20 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java	Tue Jul 10 15:02:41 2012 +0200
@@ -58,8 +58,8 @@
         for (Figure f : figures) {
             Properties p = f.getProperties();
             int predCount;
-            if (p.get("predecessorCount") != null) {
-                predCount = Integer.parseInt(p.get("predecessorCount"));
+            if (Boolean.parseBoolean(p.get("hasPredecessor"))) {
+                predCount = 1;
             } else {
                 predCount = 0;
             }