# HG changeset patch # User Gilles Duboscq # Date 1342010482 -7200 # Node ID b3d3a2fcba3d471a7ebe6cc49440f861ae3721dd # Parent 272f9da7ce78e52b0bd8717ce294face59db977c# Parent 013081f7771bf6228266a6e3754e80634c78b28d Merge diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Wed Jul 11 14:41:22 2012 +0200 @@ -140,11 +140,12 @@ public static boolean DumpOnError = ____; // Ideal graph visualizer output settings - public static int PlotLevel = 3; - public static int PrintIdealGraphLevel = 0; + public static boolean PrintBinaryGraphs = ____; + public static boolean PrintCFG = true; 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 = ____; @@ -215,6 +216,7 @@ public static boolean OptLivenessAnalysis = true; public static boolean OptLoopTransform = true; public static boolean OptSafepointElimination = true; + public static boolean FloatingReads = true; public static boolean OptTailDuplication = true; /** diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/graph/PostOrderNodeIterator.java Wed Jul 11 14:41:22 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 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java Wed Jul 11 14:41:22 2012 +0200 @@ -22,6 +22,9 @@ */ package com.oracle.graal.compiler.phases; +import java.util.*; +import java.util.concurrent.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; @@ -51,6 +54,7 @@ private NodeWorkList workList; private Tool tool; + private List snapshotTemp; public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) { this(target, runtime, assumptions, null, 0, null); @@ -82,6 +86,7 @@ this.runtime = runtime; this.immutabilityPredicate = immutabilityPredicate; this.initWorkingSet = workingSet; + this.snapshotTemp = new ArrayList<>(); } @Override @@ -97,14 +102,6 @@ } tool = new Tool(workList, runtime, target, assumptions, immutabilityPredicate); processWorkSet(graph); - - while (graph.getUsagesDroppedNodesCount() > 0) { - for (Node n : graph.getAndCleanUsagesDroppedNodes()) { - if (!n.isDeleted() && n.usages().size() == 0 && GraphUtil.isFloatingNode().apply(n)) { - n.safeDelete(); - } - } - } } public interface IsImmutablePredicate { @@ -138,8 +135,19 @@ return; } int mark = graph.getMark(); - tryCanonicalize(node, graph, tool); - tryInferStamp(node, graph); + if (!tryKillUnused(node)) { + node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp); + if (!tryCanonicalize(node, graph, tool)) { + tryInferStamp(node, graph); + } else { + for (Node in : snapshotTemp) { + if (in.isAlive() && in.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(in); + } + } + } + snapshotTemp.clear(); + } for (Node newNode : graph.getNewNodes(mark)) { workList.add(newNode); @@ -147,6 +155,14 @@ } } + private static boolean tryKillUnused(Node node) { + if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(node); + return true; + } + return false; + } + public static boolean tryGlobalValueNumbering(Node node, StructuredGraph graph) { if (node.getNodeClass().valueNumberable()) { Node newNode = graph.findDuplicate(node); @@ -162,11 +178,11 @@ return false; } - public static void tryCanonicalize(final Node node, final StructuredGraph graph, final SimplifierTool tool) { + public static boolean tryCanonicalize(final Node node, final StructuredGraph graph, final SimplifierTool tool) { if (node instanceof Canonicalizable) { METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); - Debug.scope("CanonicalizeNode", node, new Runnable() { - public void run() { + return Debug.scope("CanonicalizeNode", node, new Callable(){ + public Boolean call() { ValueNode canonical = ((Canonicalizable) node).canonical(tool); // cases: original node: // |Floating|Fixed-unconnected|Fixed-connected| @@ -182,9 +198,9 @@ // X: must not happen (checked with assertions) if (canonical == node) { Debug.log("Canonicalizer: work on %s", node); + return false; } else { Debug.log("Canonicalizer: replacing %s with %s", node, canonical); - METRIC_CANONICALIZED_NODES.increment(); if (node instanceof FloatingNode) { if (canonical == null) { @@ -192,7 +208,7 @@ graph.removeFloating((FloatingNode) node); } else { // case 2 - assert !(canonical instanceof FixedNode) || canonical.predecessor() != null : node + " -> " + canonical + + assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode) : node + " -> " + canonical + " : replacement should be floating or fixed and connected"; graph.replaceFloating((FloatingNode) node, canonical); } @@ -218,6 +234,7 @@ } } } + return true; } } }); @@ -226,6 +243,7 @@ METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment(); ((Simplifiable) node).simplify(tool); } + return false; } /** diff -r 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java Wed Jul 11 14:41:22 2012 +0200 @@ -169,7 +169,7 @@ if (virtual.fieldsCount() > 0) { final BlockExitState startState = new BlockExitState(escapeFields, virtual); - final PostOrderNodeIterator iterator = new PostOrderNodeIterator(next, startState) { + new PostOrderNodeIterator(next, startState) { @Override protected void node(FixedNode curNode) { op.updateState(virtual, curNode, fields, state.fieldState); @@ -183,8 +183,7 @@ ((StateSplit) curNode).stateAfter().addVirtualObjectMapping(v); } } - }; - iterator.apply(); + }.apply(); } } } diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Wed Jul 11 14:41:22 2012 +0200 @@ -47,7 +47,6 @@ private int deletedNodeCount; private GraphEventLog eventLog; - ArrayList usagesDropped = new ArrayList<>(); InputChangedListener inputChanged; private final HashMap cachedNodes = new HashMap<>(); @@ -149,16 +148,6 @@ return node; } - public int getUsagesDroppedNodesCount() { - return usagesDropped.size(); - } - - public List getAndCleanUsagesDroppedNodes() { - ArrayList result = usagesDropped; - usagesDropped = new ArrayList<>(); - return result; - } - public interface InputChangedListener { void inputChanged(Node node); } @@ -322,6 +311,11 @@ } return super.filter(clazz); } + + @Override + public int count() { + return getNodeCount(); + } }; } diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Wed Jul 11 14:41:22 2012 +0200 @@ -279,9 +279,6 @@ private boolean removeThisFromUsages(Node n) { if (n.usages.remove(this)) { - if (n.usages.size() == 0) { - graph.usagesDropped.add(n); - } return true; } else { return false; @@ -419,12 +416,19 @@ /** * 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<>(); - map.put("usageCount", usages.size()); - map.put("predecessorCount", predecessor == null ? 0 : 1); + 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) { getNodeClass().getDebugProperties(this, map); return map; } @@ -492,6 +496,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 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Wed Jul 11 14:41:22 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++; @@ -572,17 +579,8 @@ } } 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); + properties.put(dataNames[i], value); } } @@ -909,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 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInfo.java Wed Jul 11 14:41:22 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 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Wed Jul 11 14:41:22 2012 +0200 @@ -55,7 +55,7 @@ this.nodes = new Node[elements.length]; for (int i = 0; i < elements.length; i++) { this.nodes[i] = elements[i]; - assert this.nodes[i] == null || !this.nodes[i].isDeleted(); + assert this.nodes[i] == null || !this.nodes[i].isDeleted() : "Initializing nodelist with deleted element : " + nodes[i]; } } } @@ -254,6 +254,13 @@ return (List) Arrays.asList(Arrays.copyOf(this.nodes, this.size)); } + @Override + public void snapshotTo(List to) { + for (int i = 0; i < size; i++) { + to.add(get(i)); + } + } + @SuppressWarnings("unchecked") public void setAll(NodeList values) { incModCount(); diff -r 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/AbstractNodeIterable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/AbstractNodeIterable.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/AbstractNodeIterable.java Wed Jul 11 14:41:22 2012 +0200 @@ -65,6 +65,12 @@ return list; } @Override + public void snapshotTo(List to) { + for (T n : this) { + to.add(n); + } + } + @Override public T first() { Iterator iterator = iterator(); if (iterator.hasNext()) { diff -r 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java Wed Jul 11 14:41:22 2012 +0200 @@ -44,6 +44,8 @@ List snapshot(); + void snapshotTo(List to); + T first(); int count(); diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java Wed Jul 11 14:41:22 2012 +0200 @@ -64,13 +64,14 @@ if (logFilter != null || meterFilter != null || timerFilter != null || dumpFilter != null || methodFilter != null) { TTY.println(Thread.currentThread().getName() + ": " + toString()); } - if (GraalOptions.PrintIdealGraphFile) { - dumpHandlers.add(new IdealGraphPrinterDumpHandler()); + dumpHandlers.add(new GraphPrinterDumpHandler()); } else { - dumpHandlers.add(new IdealGraphPrinterDumpHandler(GraalOptions.PrintIdealGraphAddress, GraalOptions.PrintIdealGraphPort)); + dumpHandlers.add(new GraphPrinterDumpHandler(GraalOptions.PrintIdealGraphAddress, GraalOptions.PrintBinaryGraphPort)); } - dumpHandlers.add(new CFGPrinterObserver()); + if (GraalOptions.PrintCFG) { + dumpHandlers.add(new CFGPrinterObserver()); + } this.output = output; } diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/RegisterNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -22,10 +22,9 @@ */ package com.oracle.graal.hotspot.nodes; -import java.util.*; - 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 +32,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 +65,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 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java diff -r 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Jul 11 14:41:22 2012 +0200 @@ -696,7 +696,7 @@ private void genNewPrimitiveArray(int typeCode) { Kind kind = arrayTypeCodeToKind(typeCode); ResolvedJavaType elementType = runtime.getResolvedJavaType(kind); - NewPrimitiveArrayNode nta = currentGraph.add(new NewPrimitiveArrayNode(frameState.ipop(), elementType)); + NewPrimitiveArrayNode nta = currentGraph.add(new NewPrimitiveArrayNode(elementType, frameState.ipop())); frameState.apush(append(nta)); } diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/Block.java Wed Jul 11 14:41:22 2012 +0200 @@ -53,7 +53,6 @@ } public int getId() { - assert id >= 0; return id; } diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/CFGVerifier.java Wed Jul 11 14:41:22 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 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -62,13 +62,6 @@ } @Override - public Map getDebugProperties() { - Map debugProperties = super.getDebugProperties(); - debugProperties.put("shortName", "B"); - return debugProperties; - } - - @Override public void simplify(SimplifierTool tool) { FixedNode prev = (FixedNode) this.predecessor(); if (prev == null) { diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Wed Jul 11 14:41:22 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 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Wed Jul 11 14:41:22 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 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -28,7 +28,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -@NodeInfo(shortName = "Deopt") +@NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}") public class DeoptimizeNode extends FixedNode implements Node.IterableNodeType, LIRLowerable { private String message; diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java Wed Jul 11 14:41:22 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 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -29,10 +29,11 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +@NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}") public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, LIRLowerable, Node.IterableNodeType, Negatable { @Input private BooleanNode condition; - private final DeoptimizationReason deoptReason; + private final DeoptimizationReason reason; private final DeoptimizationAction action; private boolean negated; private final long leafGraphId; @@ -56,7 +57,7 @@ this.negated = negated; this.leafGraphId = leafGraphId; this.condition = condition; - this.deoptReason = deoptReason; + this.reason = deoptReason; } @Override @@ -70,7 +71,7 @@ @Override public void generate(LIRGeneratorTool gen) { - gen.emitGuardCheck(condition, deoptReason, action, negated, leafGraphId); + gen.emitGuardCheck(condition, reason, action, negated, leafGraphId); } @Override @@ -84,7 +85,7 @@ if (next != null) { tool.deleteBranch(next); } - setNext(graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, deoptReason, leafGraphId))); + setNext(graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, reason, leafGraphId))); return; } } @@ -92,7 +93,7 @@ @Override public void lower(LoweringTool tool) { - ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(tool.createGuard(condition, deoptReason, action, negated, leafGraphId))); + ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(tool.createGuard(condition, reason, action, negated, leafGraphId))); ((StructuredGraph) graph()).replaceFixedWithFixed(this, newAnchor); } diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Wed Jul 11 14:41:22 2012 +0200 @@ -35,6 +35,7 @@ * The {@code FrameState} class encapsulates the frame state (i.e. local variables and * operand stack) at a particular point in the abstract interpretation. */ +@NodeInfo(nameTemplate = "FrameState@{p#method/s}:{p#bci}") public final class FrameState extends VirtualState implements Node.IterableNodeType, LIRLowerable { /** @@ -352,30 +353,16 @@ } @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)); + //properties.put("method", MetaUtil.format("%H.%n(%p):%r", method)); StackTraceElement ste = method.toStackTraceElement(bci); if (ste.getFileName() != null && ste.getLineNumber() >= 0) { - properties.put("source", ste.getFileName() + ":" + ste.getLineNumber()); + properties.put("sourceFile", ste.getFileName()); + properties.put("sourceLine", ste.getLineNumber()); } - } else { - properties.put("method", "None"); - } - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < localsSize(); i++) { - sb.append(i == 0 ? "" : ", ").append(localAt(i) == null ? "_" : localAt(i).toString(Verbosity.Id)); } - properties.put("locals", sb.toString()); - sb = new StringBuilder(); - for (int i = 0; i < stackSize(); i++) { - 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 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -41,6 +41,7 @@ * maximum flexibility for the guard node and guarantees that deoptimization occurs only if the control flow would have * reached the guarded node (without taking exceptions into account). */ +@NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}") public final class GuardNode extends FloatingNode implements Canonicalizable, LIRLowerable, TypeFeedbackProvider, Node.IterableNodeType, Negatable { @Input private BooleanNode condition; diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -34,6 +34,7 @@ /** * The {@code InvokeNode} represents all kinds of method calls. */ +@NodeInfo(nameTemplate = "Invoke#{p#targetMethod/s}") public final class InvokeNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, Invoke, LIRLowerable, MemoryCheckpoint { @Input private final MethodCallTargetNode callTarget; @@ -86,10 +87,10 @@ } @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())); + debugProperties.put("targetMethod", callTarget.targetMethod()); } return debugProperties; } diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Wed Jul 11 14:41:22 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/s}") 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; @@ -161,11 +161,10 @@ } @Override - public Map getDebugProperties() { - Map debugProperties = super.getDebugProperties(); - debugProperties.put("memoryCheckpoint", "true"); + 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())); + debugProperties.put("targetMethod", callTarget.targetMethod()); } return debugProperties; } diff -r 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LocalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LocalNode.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LocalNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -30,7 +30,7 @@ * The {@code Local} instruction is a placeholder for an incoming argument * to a function call. */ - +@NodeInfo(nameTemplate = "Local({p#index})") public final class LocalNode extends FloatingNode implements Node.IterableNodeType { private final int index; diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Wed Jul 11 14:41:22 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 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Wed Jul 11 14:41:22 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 = "{p#type/s}Phi({i#values})") public final class PhiNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType { public static enum PhiType { diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes; -import java.util.*; - import com.oracle.graal.graph.*; public abstract class ScheduledNode extends Node { @@ -38,17 +36,4 @@ updatePredecessor(scheduledNext, x); scheduledNext = x; } - - @Override - public Map getDebugProperties() { - Map debugProperties = super.getDebugProperties(); - if (this instanceof StateSplit) { - StateSplit stateSplit = (StateSplit) this; - if (stateSplit.stateAfter() != null) { - debugProperties.put("stateAfter", stateSplit.stateAfter().toString(Verbosity.Debugger)); - } - } - return debugProperties; - } - } diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Wed Jul 11 14:41:22 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 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -33,6 +33,7 @@ * A location for a memory access in terms of the kind of value accessed and the displacement * (in bytes) from a base object or address. */ +@NodeInfo(nameTemplate = "Loc {p#locationIdentity/s}") public class LocationNode extends FloatingNode implements LIRLowerable, ValueNumberable { private int displacement; diff -r 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -23,10 +23,12 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.code.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +@NodeInfo(nameTemplate = "RuntimeCall#{p#call/s}") public final class RuntimeCallNode extends AbstractCallNode implements LIRLowerable { private final RuntimeCall call; diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.java; import java.lang.reflect.*; -import java.util.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; @@ -91,13 +90,6 @@ } @Override - public Map getDebugProperties() { - Map debugProperties = super.getDebugProperties(); - debugProperties.put("field", MetaUtil.format("%h.%n", field)); - return debugProperties; - } - - @Override public String toString(Verbosity verbosity) { if (verbosity == Verbosity.Name) { return super.toString(verbosity) + "#" + field.name(); diff -r 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -31,6 +31,7 @@ /** * The {@code LoadFieldNode} represents a read of a static or instance field. */ +@NodeInfo(nameTemplate = "LoadField#{p#field/s}") public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable, Node.IterableNodeType { /** diff -r 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -39,6 +39,7 @@ public abstract class NewArrayNode extends FixedWithNextNode implements Lowerable, EscapeAnalyzable, TypeFeedbackProvider { @Input private ValueNode length; + private final ResolvedJavaType elementType; public static final int MaximumEscapeAnalysisArrayLength = 32; @@ -50,9 +51,10 @@ * Constructs a new NewArrayNode. * @param length the node that produces the length for this allocation */ - protected NewArrayNode(Stamp stamp, ValueNode length) { - super(stamp); + protected NewArrayNode(ResolvedJavaType elementType, ValueNode length) { + super(StampFactory.exactNonNull(elementType.arrayOf())); this.length = length; + this.elementType = elementType; } /** @@ -64,18 +66,20 @@ } /** + * Gets the element type of the array. + * @return the element type of the array + */ + public ResolvedJavaType elementType() { + return elementType; + } + + /** * The rank of the array allocated by this node, i.e. how many array dimensions. */ public int dimensionCount() { return 1; } - /** - * Gets the element type of the array. - * @return the element type of the array - */ - public abstract ResolvedJavaType elementType(); - @Override public void typeFeedback(TypeFeedbackTool tool) { assert length.kind() == Kind.Int; @@ -130,12 +134,13 @@ AccessIndexedNode x = (AccessIndexedNode) current; if (GraphUtil.unProxify(x.array()) == node) { int index = ((AccessIndexedNode) current).index().asConstant().asInt(); + StructuredGraph graph = (StructuredGraph) x.graph(); if (current instanceof LoadIndexedNode) { x.replaceAtUsages(fieldState[index]); - ((StructuredGraph) x.graph()).removeFixed(x); + graph.removeFixed(x); } else if (current instanceof StoreIndexedNode) { fieldState[index] = ((StoreIndexedNode) x).value(); - ((StructuredGraph) x.graph()).removeFixed(x); + graph.removeFixed(x); return index; } } diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -34,6 +34,7 @@ /** * The {@code NewInstanceNode} represents the allocation of an instance class object. */ +@NodeInfo(nameTemplate = "New {p#instanceClass/s}") public final class NewInstanceNode extends FixedWithNextNode implements EscapeAnalyzable, Lowerable, LIRLowerable, Node.IterableNodeType { private final ResolvedJavaType instanceClass; @@ -65,13 +66,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 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewObjectArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewObjectArrayNode.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewObjectArrayNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -26,28 +26,20 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * The {@code NewObjectArrayNode} represents an allocation of an object array. */ +@NodeInfo(nameTemplate = "NewArray {p#elementType}") public final class NewObjectArrayNode extends NewArrayNode implements LIRLowerable, Node.IterableNodeType { - private final ResolvedJavaType elementClass; - /** * Constructs a new NewObjectArrayNode. * @param elementClass the class of elements in this array * @param length the node producing the length of the array */ public NewObjectArrayNode(ResolvedJavaType elementClass, ValueNode length) { - super(StampFactory.exactNonNull(elementClass.arrayOf()), length); - this.elementClass = elementClass; - } - - @Override - public ResolvedJavaType elementType() { - return elementClass; + super(elementClass, length); } @Override diff -r 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewPrimitiveArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewPrimitiveArrayNode.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewPrimitiveArrayNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -23,25 +23,18 @@ package com.oracle.graal.nodes.java; 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.*; /** * The {@code NewPrimitiveArrayNode} class definition. */ +@NodeInfo(nameTemplate = "NewArray {p#elementType}") public final class NewPrimitiveArrayNode extends NewArrayNode implements LIRLowerable { - private final ResolvedJavaType elementType; - - public NewPrimitiveArrayNode(ValueNode length, ResolvedJavaType elementType) { - super(StampFactory.exactNonNull(elementType.arrayOf()), length); - this.elementType = elementType; - } - - @Override - public ResolvedJavaType elementType() { - return elementType; + public NewPrimitiveArrayNode(ResolvedJavaType elementType, ValueNode length) { + super(elementType, length); } @Override diff -r 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -23,12 +23,14 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; /** * The {@code StoreFieldNode} represents a write to a static or instance field. */ +@NodeInfo(nameTemplate = "StoreField#{p#field/s}") public final class StoreFieldNode extends AccessFieldNode implements StateSplit { @Input private ValueNode value; diff -r 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Wed Jul 11 14:41:22 2012 +0200 @@ -22,21 +22,24 @@ */ package com.oracle.graal.nodes.util; -import static com.oracle.graal.graph.iterators.NodePredicates.*; - import java.util.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; -import com.oracle.graal.graph.iterators.NodePredicates.PositiveTypePredicate; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; public class GraphUtil { - private static final PositiveTypePredicate FLOATING = isA(FloatingNode.class).or(VirtualState.class).or(CallTargetNode.class); + private static final NodePredicate FLOATING = new NodePredicate() { + @Override + public final boolean apply(Node n) { + //isA(FloatingNode.class).or(VirtualState.class).or(CallTargetNode.class) + return n instanceof FloatingNode || n instanceof VirtualState || n instanceof CallTargetNode; + } + }; public static void killCFG(FixedNode node) { assert node.isAlive(); diff -r 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Wed Jul 11 14:41:22 2012 +0200 @@ -23,10 +23,11 @@ package com.oracle.graal.nodes.virtual; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; - +@NodeInfo(nameTemplate = "VirtualObject {p#type}") public class VirtualObjectNode extends FloatingNode implements LIRLowerable { private ResolvedJavaType type; diff -r 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java Wed Jul 11 14:41:22 2012 +0200 @@ -85,7 +85,13 @@ */ protected BasicIdealGraphPrinter(OutputStream stream) { try { - this.stream = new PrintStream(stream, false, "US-ASCII"); + OutputStream buffered; + if (stream instanceof BufferedOutputStream) { + buffered = stream; + } else { + buffered = new BufferedOutputStream(stream, 256 * 1024); + } + this.stream = new PrintStream(buffered, false, "US-ASCII"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } @@ -251,7 +257,7 @@ /** * Ends the current group. */ - protected void endGroup() { + public void endGroup() { stream.println(""); } diff -r 013081f7771b -r b3d3a2fcba3d 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 Wed Jul 11 14:41:22 2012 +0200 @@ -0,0 +1,442 @@ +/* + * 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.NodeClass.NodeClassIterator; +import com.oracle.graal.graph.NodeClass.Position; +import com.oracle.graal.lir.cfg.*; +import com.oracle.graal.nodes.*; + +public class BinaryGraphPrinter implements GraphPrinter{ + 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_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 POOL_FIELD = 0x07; + private static final int POOL_SIGNATURE = 0x08; + + 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; + + private static final class ConstantPool extends LinkedHashMap { + private final LinkedList availableIds; + private int nextId; + private static final long serialVersionUID = -2676889957907285681L; + public ConstantPool() { + 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 ConstantPool constantPool; + private final ByteBuffer buffer; + private final WritableByteChannel channel; + private long bytes; + private long newPoolEntry; + + public BinaryGraphPrinter(WritableByteChannel channel) { + constantPool = new ConstantPool(); + buffer = ByteBuffer.allocateDirect(256 * 1024); + this.channel = channel; + } + + public void print(Graph graph, String title, SchedulePhase predefinedSchedule) throws IOException { + long startBytes = bytes; + long startTime = System.currentTimeMillis(); + long startPool = newPoolEntry; + 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(); + Block[] blocks = cfg == null ? null : cfg.getBlocks(); + writeByte(BEGIN_GRAPH); + writePoolObject(title); + 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(); + bytes += 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; + } + if (object instanceof ResolvedJavaType) { + writePoolObject(((ResolvedJavaType) object).toJava()); + 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 NodeClass) { + writeByte(POOL_NODE_CLASS); + } else if (object instanceof ResolvedJavaMethod) { + writeByte(POOL_METHOD); + } else if (object instanceof ResolvedJavaField) { + writeByte(POOL_FIELD); + } else if (object instanceof Signature) { + writeByte(POOL_SIGNATURE); + } else { + writeByte(POOL_STRING); + } + writeInt(id.intValue()); + } + } + + 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); + writeString(klass.getName()); + if (klass.isEnum()) { + writeByte(ENUM_KLASS); + Object[] enumConstants = klass.getEnumConstants(); + writeInt(enumConstants.length); + for (Object o : enumConstants) { + writePoolObject(((Enum) o).name()); + } + } else { + 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); + ResolvedJavaMethod method = ((ResolvedJavaMethod) object); + writePoolObject(method.holder()); + writePoolObject(method.name()); + writePoolObject(method.signature()); + writeInt(method.accessFlags()); + writeBytes(method.code()); + } else if (object instanceof ResolvedJavaField) { + writeByte(POOL_FIELD); + ResolvedJavaField field = ((ResolvedJavaField) object); + writePoolObject(field.holder()); + writePoolObject(field.name()); + writePoolObject(field.type().name()); + writeInt(field.accessFlags()); + } else if (object instanceof Signature) { + writeByte(POOL_SIGNATURE); + Signature signature = ((Signature) object); + int args = signature.argumentCount(false); + writeShort((char) args); + for (int i = 0; i < args; i++) { + writePoolObject(signature.argumentTypeAt(i, null).name()); + } + writePoolObject(signature.returnType(null).name()); + } 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 != null && 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_INT); + 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 void writeNodes(Graph graph) throws IOException { + Map props = new HashMap<>(); + writeInt(graph.getNodeCount()); + for (Node node : graph.getNodes()) { + NodeClass nodeClass = node.getNodeClass(); + node.getDebugProperties(props); + writeInt(node.getId()); + writePoolObject(nodeClass); + writeByte(node.predecessor() == null ? 0 : 1); + writeShort((char) props.size()); + for (Entry entry : props.entrySet()) { + String key = entry.getKey().toString(); + writePoolObject(key); + writePropertyObject(entry.getValue()); + } + // successors + 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 + 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, BlockMap> blockToNodes) throws IOException { + if (blocks != null) { + writeInt(blocks.length); + for (Block block : blocks) { + List nodes = blockToNodes.get(block); + writeInt(block.getId()); + writeInt(nodes.size()); + for (Node node : nodes) { + writeInt(node.getId()); + } + writeInt(block.getSuccessors().size()); + for (Block sux : block.getSuccessors()) { + 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 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinter.java Wed Jul 11 14:41:22 2012 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2012, 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 com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.schedule.*; +import com.oracle.graal.graph.*; + +interface GraphPrinter { + /** + * Starts a new group of graphs with the given name, short name and method byte code index (BCI) as properties. + */ + void beginGroup(String name, String shortName, ResolvedJavaMethod method, int bci) throws IOException; + + /** + * Prints an entire {@link Graph} with the specified title, optionally using short names for nodes. + */ + void print(Graph graph, String title, SchedulePhase predefinedSchedule) throws IOException; + + /** + * Ends the current group. + */ + void endGroup() throws IOException; +} diff -r 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java Wed Jul 11 14:41:22 2012 +0200 @@ -0,0 +1,209 @@ +/* + * 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.text.*; +import java.util.*; + +import com.oracle.max.criutils.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.*; +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 GraphPrinterDumpHandler implements DebugDumpHandler { + private static final SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd-HHmm"); + + private GraphPrinter printer; + private List previousInlineContext = new ArrayList<>(); + private String host; + private int port; + private int failuresCount; + + /** + * Creates a new {@link GraphPrinterDumpHandler} that writes output to a file. + */ + public GraphPrinterDumpHandler() { + } + + /** + * Creates a new {@link GraphPrinterDumpHandler} that sends output to a remote IdealGraphVisualizer instance. + */ + public GraphPrinterDumpHandler(String host, int port) { + this.host = host; + this.port = port; + } + + private void ensureInitialized() { + if (printer == null) { + if (failuresCount > 8) { + return; + } + previousInlineContext.clear(); + if (host == null) { + initializeFilePrinter(); + } else { + initializeNetworkPrinter(); + } + } + } + + private void initializeFilePrinter() { + try { + String ext; + if (GraalOptions.PrintBinaryGraphs) { + ext = ".bgv"; + } else { + ext = ".gv.xml"; + } + String fileName = "Graphs-" + Thread.currentThread().getName() + "-" + sdf.format(new Date()) + ext; + if (GraalOptions.PrintBinaryGraphs) { + printer = new BinaryGraphPrinter(FileChannel.open(new File(fileName).toPath())); + } else { + printer = new IdealGraphPrinter(new FileOutputStream(fileName)); + } + TTY.println("Dumping IGV graphs to %s", fileName); + } catch (IOException e) { + failuresCount++; + printer = null; + } + } + + private void initializeNetworkPrinter() { + try { + + if (GraalOptions.PrintBinaryGraphs) { + printer = new BinaryGraphPrinter(SocketChannel.open(new InetSocketAddress(host, port))); + } else { + IdealGraphPrinter xmlPrinter = new IdealGraphPrinter(new Socket(host, port).getOutputStream()); + xmlPrinter.begin(); + printer = xmlPrinter; + } + TTY.println("Connected to the IGV on %s:%d", host, port); + } catch (IOException e) { + TTY.println("Could not connect to the IGV on %s:%d: %s", host, 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 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Wed Jul 11 14:41:22 2012 +0200 @@ -40,7 +40,7 @@ * Generates a representation of {@link Graph Graphs} that can be visualized and inspected with the Ideal Graph Visualizer. */ -class IdealGraphPrinter extends BasicIdealGraphPrinter { +class IdealGraphPrinter extends BasicIdealGraphPrinter implements GraphPrinter { /** * Creates a new {@link IdealGraphPrinter} that writes to the specified output stream. */ @@ -51,6 +51,7 @@ /** * Starts a new group of graphs with the given name, short name and method byte code index (BCI) as properties. */ + @Override public void beginGroup(String name, String shortName, ResolvedJavaMethod method, int bci) { beginGroup(); beginProperties(); @@ -70,6 +71,7 @@ /** * Prints an entire {@link Graph} with the specified title, optionally using short names for nodes. */ + @Override public void print(Graph graph, String title, SchedulePhase predefinedSchedule) { beginGraph(title); Set noBlockNodes = new HashSet<>(); @@ -79,12 +81,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(); @@ -93,10 +95,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(); @@ -158,11 +160,38 @@ printProperty(bit, "true"); } } + if (node.getClass() == BeginNode.class) { + printProperty("shortName", "B"); + } else if (node.getClass() == EndNode.class) { + printProperty("shortName", "E"); + } + if (node.predecessor() != null) { + printProperty("hasPredecessor", "true"); + } for (Entry entry : props.entrySet()) { String key = entry.getKey().toString(); - String value = entry.getValue() == null ? "null" : entry.getValue().toString(); - printProperty(key, value); + Object value = entry.getValue(); + String valueString; + if (value == null) { + valueString = "null"; + } else { + Class type = value.getClass(); + if (type.isArray()) { + if (!type.getComponentType().isPrimitive()) { + valueString = Arrays.toString((Object[]) value); + } else if (type.getComponentType() == Integer.TYPE) { + valueString = Arrays.toString((int[]) value); + } else if (type.getComponentType() == Double.TYPE) { + valueString = Arrays.toString((double[]) value); + } else { + valueString = toString(); + } + } else { + valueString = value.toString(); + } + } + printProperty(key, valueString); } endProperties(); diff -r 013081f7771b -r b3d3a2fcba3d graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinterDumpHandler.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinterDumpHandler.java Tue Jul 10 14:11:40 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -/* - * 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.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 IdealGraphPrinterDumpHandler implements DebugDumpHandler { - - private static final String DEFAULT_FILE_NAME = "output.igv.xml"; - - private IdealGraphPrinter printer; - private List previousInlineContext = new ArrayList<>(); - private String fileName; - private String host; - private int port; - private boolean initialized; - - /** - * Creates a new {@link IdealGraphPrinterDumpHandler} that writes output to a file named after the compiled method. - */ - public IdealGraphPrinterDumpHandler() { - this.fileName = DEFAULT_FILE_NAME; - } - - /** - * Creates a new {@link IdealGraphPrinterDumpHandler} that sends output to a remote IdealGraphVisualizer instance. - */ - public IdealGraphPrinterDumpHandler(String host, int port) { - this.host = host; - this.port = port; - } - - private void ensureInitialized() { - if (!initialized) { - initialized = true; - if (fileName != null) { - initializeFilePrinter(); - } else { - initializeNetworkPrinter(); - } - } - } - - private void initializeFilePrinter() { - try { - FileOutputStream stream = new FileOutputStream(fileName); - printer = new IdealGraphPrinter(stream); - printer.begin(); - } catch (IOException e) { - printer = null; - } - } - - private void initializeNetworkPrinter() { - try { - Socket socket = new Socket(host, port); - BufferedOutputStream stream = new BufferedOutputStream(socket.getOutputStream(), 0x4000); - printer = new IdealGraphPrinter(stream); - printer.begin(); - 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); - printer = null; - } - } - - @Override - public void dump(Object object, final String message) { - if (object instanceof Graph) { - ensureInitialized(); - final Graph graph = (Graph) object; - - if (printer != null && printer.isValid()) { - // Get all current ResolvedJavaMethod 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. - printer.print(graph, message); - - } - }); - } - } - } - - 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() + ":" : ""; - printer.beginGroup(prefix + name, name, Debug.contextLookup(ResolvedJavaMethod.class), -1); - } - - private void closeScope() { - printer.endGroup(); - } -} diff -r 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java Wed Jul 11 14:41:22 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 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java Wed Jul 11 14:41:22 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 013081f7771b -r b3d3a2fcba3d 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 Wed Jul 11 14:41:22 2012 +0200 @@ -0,0 +1,740 @@ +/* + * 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.Properties; +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; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +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_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 POOL_FIELD = 0x07; + private static final int POOL_SIGNATURE = 0x08; + + 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 final ByteBuffer buffer; + private final ReadableByteChannel channel; + private Deque folderStack; + + private enum Length { + S, + M, + L + } + + private interface LengthToString { + String toString(Length l); + } + + private static abstract class Member implements LengthToString { + public final Klass holder; + public final int accessFlags; + public final String name; + public Member(Klass holder, String name, int accessFlags) { + this.holder = holder; + this.accessFlags = accessFlags; + this.name = name; + } + } + + private static class Method extends Member { + public final Signature signature; + public final byte[] code; + public Method(String name, Signature signature, byte[] code, Klass holder, int accessFlags) { + super(holder, name, accessFlags); + this.signature = signature; + this.code = code; + } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(holder).append('.').append(name).append('('); + for (int i = 0; i < signature.argTypes.length; i++) { + if (i > 0) { + sb.append(", "); + } + sb.append(signature.argTypes[i]); + } + sb.append(')'); + return sb.toString(); + } + @Override + public String toString(Length l) { + switch(l) { + case M: + return holder.toString(Length.L) + "." + name; + case S: + return holder.toString(Length.S) + "." + name; + default: + case L: + return toString(); + } + } + } + + private static class Signature { + public final String returnType; + public final String[] argTypes; + public Signature(String returnType, String[] argTypes) { + this.returnType = returnType; + this.argTypes = argTypes; + } + } + + private static class Field extends Member { + public final String type; + public Field(String type, Klass holder, String name, int accessFlags) { + super(holder, name, accessFlags); + this.type = type; + } + @Override + public String toString() { + return holder + "." + name; + } + @Override + public String toString(Length l) { + switch(l) { + case M: + return holder.toString(Length.L) + "." + name; + case S: + return holder.toString(Length.S) + "." + name; + default: + case L: + return toString(); + } + } + } + + private static class Klass implements LengthToString { + public final String name; + public final String simpleName; + public Klass(String name) { + this.name = name; + String simple; + try { + simple = name.substring(name.lastIndexOf('.') + 1); + } catch (IndexOutOfBoundsException ioobe) { + simple = name; + } + this.simpleName = simple; + } + @Override + public String toString() { + return name; + } + @Override + public String toString(Length l) { + switch(l) { + case S: + return simpleName; + default: + case L: + case M: + return toString(); + } + } + } + + private static class EnumKlass extends Klass { + public final String[] values; + public EnumKlass(String name, String[] values) { + super(name); + this.values = values; + } + } + + 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; + } + @Override + public String toString() { + return className; + } + } + + private static class EnumValue implements LengthToString { + public EnumKlass enumKlass; + public int ordinal; + public EnumValue(EnumKlass enumKlass, int ordinal) { + this.enumKlass = enumKlass; + this.ordinal = ordinal; + } + @Override + public String toString() { + return enumKlass.simpleName + "." + enumKlass.values[ordinal]; + } + @Override + public String toString(Length l) { + switch(l) { + case S: + return enumKlass.values[ordinal]; + default: + case M: + case L: + return toString(); + } + } + } + + public BinaryParser(GroupCallback callback, ReadableByteChannel channel) { + this.callback = callback; + constantPool = new ArrayList<>(); + buffer = ByteBuffer.allocateDirect(256 * 1024); + buffer.flip(); + this.channel = channel; + folderStack = new LinkedList<>(); + } + + private void fill() throws IOException { + buffer.compact(); + if (channel.read(buffer) < 0) { + throw new EOFException(); + } + 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); + } + assert assertObjectType(klass, type); + 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(EnumKlass.class); + case POOL_ENUM: + return klass.isAssignableFrom(EnumValue.class); + case POOL_METHOD: + return klass.isAssignableFrom(Method.class); + case POOL_STRING: + return klass.isAssignableFrom(String.class); + case POOL_NODE_CLASS: + return klass.isAssignableFrom(NodeClass.class); + case POOL_FIELD: + return klass.isAssignableFrom(Field.class); + case POOL_SIGNATURE: + return klass.isAssignableFrom(Signature.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 : " + klasstype); + } + break; + } + case POOL_ENUM: { + EnumKlass enumClass = readPoolObject(EnumKlass.class); + 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: { + Klass holder = readPoolObject(Klass.class); + String name = readPoolObject(String.class); + Signature sign = readPoolObject(Signature.class); + int flags = readInt(); + byte[] code = readBytes(); + obj = new Method(name, sign, code, holder, flags); + break; + } + case POOL_FIELD: { + Klass holder = readPoolObject(Klass.class); + String name = readPoolObject(String.class); + String fType = readPoolObject(String.class); + int flags = readInt(); + obj = new Field(fType, holder, name, flags); + break; + } + case POOL_SIGNATURE: { + int argc = readShort(); + String[] args = new String[argc]; + for (int i = 0; i < argc; i++) { + args[i] = readPoolObject(String.class); + } + String returnType = readPoolObject(String.class); + obj = new Signature(returnType, args); + 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()); + try { + while(true) { + parseRoot(); + } + } catch (EOFException e) { + + } + } + + 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); + Method method = readPoolObject(Method.class); + int bci = readInt(); + Group group = new Group(parent); + group.getProperties().setProperty("name", name); + if (method != null) { + InputMethod inMethod = new InputMethod(group, method.name, shortName, bci); + inMethod.setBytecodes("TODO"); + group.setMethod(inMethod); + } + return group; + } + + private InputGraph parseGraph() throws IOException { + String title = readPoolObject(String.class); + InputGraph graph = new InputGraph(title); + parseNodes(graph); + parseBlocks(graph); + graph.ensureNodesInBlocks(); + return graph; + } + + 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++) { + 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)); + } + } + 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 parseNodes(InputGraph graph) throws IOException { + int count = readInt(); + Map props = new HashMap<>(); + List edges = new LinkedList<>(); + for (int i = 0; i < count; i++) { + int id = readInt(); + InputNode node = new InputNode(id); + final Properties properties = node.getProperties(); + NodeClass nodeClass = readPoolObject(NodeClass.class); + int preds = readByte(); + if (preds > 0) { + properties.setProperty("hasPredecessor", "true"); + } + int propCount = readShort(); + for (int j = 0; j < propCount; j++) { + String key = readPoolObject(String.class); + Object value = readPropertyObject(); + properties.setProperty(key, value != null ? value.toString() : "null"); + props.put(key, value); + } + 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) (preds + j), nodeClass.inputs.get(index), true)); + } + properties.setProperty("name", createName(edges.subList(edgesStart, edges.size()), props, nodeClass.nameTemplate)); + properties.setProperty("class", nodeClass.className); + switch (nodeClass.className) { + case "BeginNode": + properties.setProperty("shortName", "B"); + break; + case "EndNode": + properties.setProperty("shortName", "E"); + break; + } + graph.addNode(node); + props.clear(); + } + for (Edge e : edges) { + char fromIndex = e.input ? 1 : 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, Map properties, String template) { + Pattern p = Pattern.compile("\\{(p|i)#([a-zA-Z0-9$_]+)(/(l|m|s))?\\}"); + 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": + Object prop = properties.get(name); + String length = m.group(4); + if (prop == null) { + result = "?"; + } else if (length != null && prop instanceof LengthToString) { + LengthToString lengthProp = (LengthToString) prop; + switch(length) { + default: + case "l": + result = lengthProp.toString(Length.L); + break; + case "m": + result = lengthProp.toString(Length.M); + break; + case "s": + result = lengthProp.toString(Length.S); + break; + } + } else { + result = prop.toString(); + } + 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 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java Wed Jul 11 14:41:22 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; } diff -r 013081f7771b -r b3d3a2fcba3d src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter --- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter Tue Jul 10 14:11:40 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter Wed Jul 11 14:41:22 2012 +0200 @@ -9,4 +9,7 @@ colorize("name", "Comp .*", yellow); colorize("name", "Virtual.*", green); -colorize("notInOwnBlock", "true", red); \ No newline at end of file +colorize("name", "ValuePhi.*|ValueProxy", magenta); +colorize("name", "Const.*", new java.awt.Color(0.7, 0.7, 0.7)); +colorize("name", "Local.*", new java.awt.Color(0.85, 0.85, 0.85)); +colorize("stamp", "Condition", yellow); \ No newline at end of file diff -r 013081f7771b -r b3d3a2fcba3d src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/noframestate.filter --- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/noframestate.filter Tue Jul 10 14:11:40 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/noframestate.filter Wed Jul 11 14:41:22 2012 +0200 @@ -1,1 +1,2 @@ -remove("class", "FrameState"); \ No newline at end of file +remove("class", "FrameState"); +remove("class", "Virtual.*"); \ No newline at end of file diff -r 013081f7771b -r b3d3a2fcba3d 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 Wed Jul 11 14:41:22 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 013081f7771b -r b3d3a2fcba3d 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 Wed Jul 11 14:41:22 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 013081f7771b -r b3d3a2fcba3d 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 Tue Jul 10 14:11:40 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/Settings.java Wed Jul 11 14:41:22 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");