# HG changeset patch # User Gilles Duboscq # Date 1341925361 -7200 # Node ID 3b8bc07f8d17c9a8852e8b0258def7bbe65e17a7 # Parent 32613b375b30ecd80e6054da8c2e031495b4d312 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) diff -r 32613b375b30 -r 3b8bc07f8d17 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 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 getDebugProperties() { - Map 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 getDebugProperties(Map map) { map.put("usageCount", usages.size()); - map.put("predecessorCount", predecessor == null ? 0 : 1); + map.put("hasPredecessor", predecessor != null); getNodeClass().getDebugProperties(this, map); return map; } diff -r 32613b375b30 -r 3b8bc07f8d17 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 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 getFirstLevelInputPositions() { + List 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 getFirstLevelSuccessorPositions() { + List 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 {i#inputName} or {p#propertyName}. + */ + public String getNameTemplate() { + return nameTemplate; } static Map addGraphDuplicate(Graph graph, Iterable nodes, DuplicationReplacement replacements) { diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInfo.java --- 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 {i#inputName} or {p#propertyName}. + */ + String nameTemplate() default ""; } diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/RegisterNode.java --- 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 getDebugProperties() { - Map properties = super.getDebugProperties(); - properties.put("register", register.toString()); - return properties; - } - @SuppressWarnings("unused") @NodeIntrinsic public static T register(@ConstantNodeParameter Register register, @ConstantNodeParameter Kind kind) { diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java --- 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 getDebugProperties() { - Map debugProperties = super.getDebugProperties(); - debugProperties.put("size", String.valueOf(size)); - return debugProperties; - } - /** * @return null if allocation fails */ diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java --- 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 getDebugProperties() { - Map debugProperties = super.getDebugProperties(); + public Map getDebugProperties(Map map) { + Map debugProperties = super.getDebugProperties(map); debugProperties.put("shortName", "B"); return debugProperties; } diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java --- 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 getDebugProperties(Map map) { + Map 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()) + ")"; diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java --- 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 getDebugProperties() { - Map 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) { diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java --- 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 getDebugProperties() { - Map debugProperties = super.getDebugProperties(); - debugProperties.put("shortName", "E"); - return debugProperties; - } - - @Override public Iterable< ? extends Node> cfgSuccessors() { return Arrays.asList(merge()); } diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java --- 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 getDebugProperties() { - Map properties = super.getDebugProperties(); - properties.put("bci", bci); + public Map getDebugProperties(Map map) { + Map 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; } diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java --- 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 getDebugProperties() { - Map debugProperties = super.getDebugProperties(); + public Map getDebugProperties(Map map) { + Map debugProperties = super.getDebugProperties(map); if (callTarget != null && callTarget.targetMethod() != null) { debugProperties.put("targetMethod", MetaUtil.format("%h.%n(%p)", callTarget.targetMethod())); } diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- 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 getDebugProperties() { - Map debugProperties = super.getDebugProperties(); + public Map getDebugProperties(Map map) { + Map debugProperties = super.getDebugProperties(map); debugProperties.put("memoryCheckpoint", "true"); if (callTarget != null && callTarget.targetMethod() != null) { debugProperties.put("targetMethod", MetaUtil.format("%h.%n(%p)", callTarget.targetMethod())); diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java --- 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 getDebugProperties() { - Map properties = super.getDebugProperties(); - properties.put("loopFrequency", String.format("%7.1f", loopFrequency)); - return properties; - } - public int nextEndIndex() { return nextEndIndex++; } diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java --- 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 { diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java --- 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 getDebugProperties() { - Map debugProperties = super.getDebugProperties(); + public Map getDebugProperties(Map map) { + Map debugProperties = super.getDebugProperties(map); if (this instanceof StateSplit) { StateSplit stateSplit = (StateSplit) this; if (stateSplit.stateAfter() != null) { diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java --- 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 getDebugProperties() { - Map properties = super.getDebugProperties(); + public Map getDebugProperties(Map map) { + Map properties = super.getDebugProperties(map); if (!dependencies.isEmpty()) { StringBuilder str = new StringBuilder(); for (int i = 0; i < dependencies.size(); i++) { diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java --- 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 getDebugProperties() { - Map debugProperties = super.getDebugProperties(); + public Map getDebugProperties(Map map) { + Map debugProperties = super.getDebugProperties(map); debugProperties.put("field", MetaUtil.format("%h.%n", field)); return debugProperties; } diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java --- 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 getDebugProperties() { - Map properties = super.getDebugProperties(); - properties.put("instanceClass", instanceClass); - return properties; - } - public EscapeOp getEscapeOp() { return ESCAPE; } diff -r 32613b375b30 -r 3b8bc07f8d17 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java --- 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 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> 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 directInputPositions = nodeClass.getFirstLevelInputPositions(); + writeShort((char) directInputPositions.size()); + for (Position pos : directInputPositions) { + writePoolObject(nodeClass.getName(pos)); + } + List 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 nodeToBlock, Set noBlockNodes) throws IOException { - int edges = 0; + private void writeNodes(Graph graph) throws IOException { Map 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 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 noBlockNodes, BlockMap> blockToNodes) throws IOException { + private void writeBlocks(Block[] blocks, BlockMap> blockToNodes) throws IOException { if (blocks != null) { - writeInt(blocks.length + (noBlockNodes.isEmpty() ? 0 : 1)); - int suxCount = 0; + writeInt(blocks.length); for (Block block : blocks) { List 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()); } } diff -r 32613b375b30 -r 3b8bc07f8d17 src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java --- 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 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 inputs; + public final List sux; + private NodeClass(String className, String nameTemplate, List inputs, List 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 inputs = new ArrayList<>(inputCount); + for (int i = 0; i < inputCount; i++) { + inputs.add(readPoolObject(String.class)); + } + int suxCount = readShort(); + List 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 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 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 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; + } } } diff -r 32613b375b30 -r 3b8bc07f8d17 src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java --- 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; }