changeset 2799:e1dad0edd57a

first part of loop reworking
author Lukas Stadler <lukas.stadler@jku.at>
date Fri, 27 May 2011 17:48:28 +0200
parents 58e65eb6bb5d
children 6a1e5d7e1f4e
files graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java graal/GraalCompiler/src/com/sun/c1x/debug/GraphvizPrinterObserver.java graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java graal/GraalCompiler/src/com/sun/c1x/ir/LoopBegin.java graal/GraalCompiler/src/com/sun/c1x/ir/LoopEnd.java graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java graal/GraalGraphviz/src/com/oracle/graal/graph/vis/GraphvizPrinter.java src/share/vm/compiler/compilerOracle.cpp
diffstat 14 files changed, 285 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java	Fri May 27 14:20:30 2011 +0200
+++ b/graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java	Fri May 27 17:48:28 2011 +0200
@@ -86,6 +86,13 @@
                     return false;
                 }
 
+                if (n instanceof LoopBegin) {
+                    // a LoopBegin is always a merge
+                    assignBlock(n);
+                    blockBeginNodes.add(n);
+                    return true;
+                }
+
                 Node singlePred = null;
                 for (Node pred : n.predecessors()) {
                     if (isCFG(pred)) {
@@ -147,10 +154,15 @@
                     predBlock.addSuccessor(block);
                 }
             }
+            if (n instanceof LoopBegin) {
+                LoopBegin loopBegin = (LoopBegin) n;
+                nodeToBlock.get(loopBegin.loopEnd()).addSuccessor(block);
+//                System.out.println("added LoopEnd to LoopBegin successor 2: " + loopBegin.loopEnd() + "->" + loopBegin);
+            }
         }
 
         orderBlocks();
-        //print();
+//        print();
     }
 
     private void orderBlocks() {
--- a/graal/GraalCompiler/src/com/sun/c1x/debug/GraphvizPrinterObserver.java	Fri May 27 14:20:30 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/debug/GraphvizPrinterObserver.java	Fri May 27 17:48:28 2011 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.vis.*;
 import com.sun.c1x.*;
+import com.sun.c1x.ir.*;
 import com.sun.c1x.observer.*;
 import com.sun.c1x.value.*;
 
@@ -70,26 +71,14 @@
             try {
                 if (pdf) {
                     ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-                    GraphvizPrinter printer = new GraphvizPrinter(buffer);
-                    if (C1XOptions.OmitDOTFrameStates) {
-                        printer.addOmittedClass(FrameState.class);
-                    }
-                    printer.begin(name);
-                    printer.print(graph, true);
-                    printer.end();
+                    printGraph(graph, name, buffer);
 
                     out = new FileOutputStream(filename + ".pdf");
                     GraphvizRunner.process(GraphvizRunner.DOT_LAYOUT, new ByteArrayInputStream(buffer.toByteArray()), out, "pdf");
                 } else {
                     out = new FileOutputStream(filename + ".gv");
 
-                    GraphvizPrinter printer = new GraphvizPrinter(out);
-                    if (C1XOptions.OmitDOTFrameStates) {
-                        printer.addOmittedClass(FrameState.class);
-                    }
-                    printer.begin(name);
-                    printer.print(graph, true);
-                    printer.end();
+                    printGraph(graph, name, out);
                 }
             } catch (IOException e) {
                 e.printStackTrace();
@@ -103,4 +92,20 @@
             }
         }
     }
+
+    private static void printGraph(Graph graph, String name, OutputStream buffer) {
+        GraphvizPrinter printer = new GraphvizPrinter(buffer);
+        if (C1XOptions.OmitDOTFrameStates) {
+            printer.addOmittedClass(FrameState.class);
+        }
+        printer.addClassColor(StartNode.class, "snow3");
+        printer.addClassColor(EndNode.class, "snow3");
+        printer.addClassColor(LoopBegin.class, "skyblue");
+        printer.addClassColor(LoopEnd.class, "skyblue3");
+        printer.addClassColor(Unwind.class, "red");
+        printer.addClassColor(Return.class, "indianred1");
+        printer.begin(name);
+        printer.print(graph, true);
+        printer.end();
+    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Fri May 27 14:20:30 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Fri May 27 17:48:28 2011 +0200
@@ -287,6 +287,9 @@
 
     public void mergeOrClone(Block target, FrameStateAccess newState) {
         Instruction first = target.firstInstruction;
+        if (target.isLoopHeader && isVisited(target)) {
+            first = ((LoopBegin) first).loopEnd();
+        }
         assert first instanceof StateSplit;
 
         int bci = target.startBci;
@@ -294,13 +297,13 @@
         FrameState existingState = ((StateSplit) first).stateBefore();
 
         if (existingState == null) {
-            assert first instanceof Merge ^ !target.isLoopHeader : "isLoopHeader: " + target.isLoopHeader;
+//            assert first instanceof Merge ^ !target.isLoopHeader : "isLoopHeader: " + target.isLoopHeader;
 
             // copy state because it is modified
             FrameState duplicate = newState.duplicate(bci);
 
             // if the block is a loop header, insert all necessary phis
-            if (target.isLoopHeader) {
+            if (first instanceof LoopBegin && target.isLoopHeader) {
                 assert first instanceof Merge;
                 insertLoopPhis((Merge) first, duplicate);
                 ((Merge) first).setStateBefore(duplicate);
@@ -318,16 +321,18 @@
             assert existingState.stackSize() == newState.stackSize();
 
             if (first instanceof Placeholder) {
-                Merge merge = new Merge(existingState.bci, target.isLoopHeader, graph);
+                assert !target.isLoopHeader;
+                Merge merge = new Merge(graph);
 
                 Placeholder p = (Placeholder) first;
                 assert p.next() == null;
                 p.replace(merge);
                 target.firstInstruction = merge;
                 merge.setStateBefore(existingState);
+                first = merge;
             }
 
-            existingState.merge((Merge) target.firstInstruction, newState);
+            existingState.merge((Merge) first, newState);
         }
 
         for (int j = 0; j < frameState.localsSize() + frameState.stackSize(); ++j) {
@@ -1056,7 +1061,6 @@
     }
 
     private Instruction createTarget(Block block, FrameStateAccess stateAfter) {
-
         assert block != null && stateAfter != null;
         assert block.isLoopHeader || block.firstInstruction == null || block.firstInstruction.next() == null : "non-loop block must be iterated after all its predecessors";
 
@@ -1066,14 +1070,24 @@
 
         if (block.firstInstruction == null) {
             if (block.isLoopHeader) {
-                block.firstInstruction = new Merge(block.startBci, block.isLoopHeader, graph);
+//                block.firstInstruction = new Merge(block.startBci, graph);
+
+                LoopBegin loopBegin = new LoopBegin(graph);
+                LoopEnd loopEnd = new LoopEnd(graph);
+                loopEnd.setLoopBegin(loopBegin);
+                block.firstInstruction = loopBegin;
             } else {
                 block.firstInstruction = new Placeholder(graph);
             }
         }
         mergeOrClone(block, stateAfter);
         addToWorkList(block);
-        return block.firstInstruction;
+
+        if (block.firstInstruction instanceof LoopBegin && isVisited(block)) {
+            return ((LoopBegin) block.firstInstruction).loopEnd();
+        } else {
+            return block.firstInstruction;
+        }
     }
 
     private Value synchronizedObject(FrameStateAccess state, RiMethod target) {
@@ -1135,6 +1149,28 @@
                 }
             }
         }
+        for (Block b : blocksVisited) {
+            if (b.isLoopHeader) {
+                LoopBegin begin = (LoopBegin) b.firstInstruction;
+                LoopEnd end = begin.loopEnd();
+
+//              This can happen with degenerated loops like this one:
+//                for (;;) {
+//                    try {
+//                        break;
+//                    } catch (UnresolvedException iioe) {
+//                    }
+//                }
+                if (end.stateBefore() != null) {
+                    begin.stateBefore().merge(begin, end.stateBefore());
+                } else {
+                    end.delete();
+                    Merge merge = new Merge(graph);
+                    merge.successors().setAndClear(merge.nextIndex(), begin, begin.nextIndex());
+                    begin.replace(merge);
+                }
+            }
+        }
     }
 
     private void createExceptionDispatch(ExceptionBlock block) {
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java	Fri May 27 14:20:30 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java	Fri May 27 17:48:28 2011 +0200
@@ -58,7 +58,6 @@
 
     public Instruction setBlockSuccessor(int index, Instruction n) {
         assert index >= 0 && index < blockSuccessorCount;
-//        assert n == null || n instanceof BlockBegin : "only BlockBegins, for now... " + n.getClass();
         return (Merge) successors().set(super.successorCount() + SUCCESSOR_COUNT + index, n);
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java	Fri May 27 14:20:30 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java	Fri May 27 17:48:28 2011 +0200
@@ -46,7 +46,7 @@
     private static final int INPUT_COUNT = 0;
 
     private static final int SUCCESSOR_COUNT = 1;
-    private static final int SUCCESSOR_NEXT = 0;
+    public static final int SUCCESSOR_NEXT = 0;
 
     @Override
     protected int inputCount() {
@@ -70,6 +70,10 @@
         return successors().set(super.successorCount() + SUCCESSOR_NEXT, next);
     }
 
+    public int nextIndex() {
+        return super.successorCount() + SUCCESSOR_NEXT;
+    }
+
 
     public static final int SYNCHRONIZATION_ENTRY_BCI = -1;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/LoopBegin.java	Fri May 27 17:48:28 2011 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.oracle.graal.graph.*;
+import com.sun.c1x.debug.*;
+
+public class LoopBegin extends Merge {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public LoopBegin(Graph graph) {
+        super(INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    public LoopEnd loopEnd() {
+        for (Node usage : usages()) {
+            if (usage instanceof LoopEnd) {
+                LoopEnd end = (LoopEnd) usage;
+                if (end.loopBegin() == this) {
+                    return end;
+                }
+            }
+        }
+        assert false : "Begin should always have a LoopEnd";
+        return null;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitLoopBegin(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("loopBegin");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/LoopEnd.java	Fri May 27 17:48:28 2011 +0200
@@ -0,0 +1,72 @@
+/*
+ * 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.sun.c1x.ir;
+
+import com.oracle.graal.graph.*;
+import com.sun.c1x.debug.*;
+
+
+public class LoopEnd extends Merge {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_LOOP_BEGIN = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction which produces the input value to this instruction.
+     */
+     public LoopBegin loopBegin() {
+        return (LoopBegin) inputs().get(super.inputCount() + INPUT_LOOP_BEGIN);
+    }
+
+    public LoopBegin setLoopBegin(LoopBegin n) {
+        return (LoopBegin) inputs().set(super.inputCount() + INPUT_LOOP_BEGIN, n);
+    }
+
+    public LoopEnd(Graph graph) {
+        super(INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitLoopEnd(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("loopEnd ").print(loopBegin());
+    }
+
+
+}
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java	Fri May 27 14:20:30 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java	Fri May 27 17:48:28 2011 +0200
@@ -33,7 +33,7 @@
  * about the basic block, including the successor and
  * predecessor blocks, exception handlers, liveness information, etc.
  */
-public final class Merge extends StateSplit {
+public class Merge extends StateSplit {
 
     private static final int INPUT_COUNT = 0;
 
@@ -54,32 +54,18 @@
         return false;
     }
 
-    public final boolean isLoopHeader;
-
-    /**
-     * Index of bytecode that generated this node when appended in a basic block.
-     * Negative values indicate special cases.
-     */
-    private int bci;
-
     /**
      * Constructs a new Merge at the specified bytecode index.
      * @param bci the bytecode index of the start
      * @param blockID the ID of the block
      * @param graph
      */
-    public Merge(int bci, boolean isLoopHeader, Graph graph) {
+    public Merge(Graph graph) {
         super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        this.bci = bci;
-        this.isLoopHeader = isLoopHeader;
     }
 
-    /**
-     * Gets the bytecode index of this instruction.
-     * @return the bytecode index of this instruction
-     */
-    public int bci() {
-        return bci;
+    protected Merge(int inputCount, int successorCount, Graph graph) {
+        super(CiKind.Illegal, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
     }
 
     @Override
@@ -99,12 +85,14 @@
             builder.append(" -> ");
             boolean hasSucc = false;
             for (Node s : this.successors()) {
-                if (hasSucc) {
-                    builder.append(", ");
+                if (s != null) {
+                    if (hasSucc) {
+                        builder.append(", ");
+                    }
+                    builder.append("#");
+                    builder.append(s.id());
+                    hasSucc = true;
                 }
-                builder.append("#");
-                builder.append(s.id());
-                hasSucc = true;
             }
         //}
         return builder.toString();
@@ -264,8 +252,4 @@
         return sb.toString();
     }
 
-    @Override
-    public String shortName() {
-        return "Merge #" + id();
-    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java	Fri May 27 14:20:30 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java	Fri May 27 17:48:28 2011 +0200
@@ -120,7 +120,18 @@
 
     @Override
     public String shortName() {
-        return "Phi: (" + valueCount() + ")";
+        StringBuilder str = new StringBuilder();
+        for (int i = 1; i < inputs().size(); ++i) {
+            if (i != 1) {
+                str.append(' ');
+            }
+            if (inputs().get(i) != null) {
+                str.append(inputs().get(i).id());
+            } else {
+                str.append("-");
+            }
+        }
+        return "Phi: (" + str + ")";
     }
 
     public Phi addInput(Node y) {
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java	Fri May 27 14:20:30 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java	Fri May 27 17:48:28 2011 +0200
@@ -70,4 +70,6 @@
     public abstract void visitDeoptimize(Deoptimize deoptimize);
     public abstract void visitExceptionDispatch(ExceptionDispatch exceptionDispatch);
     public abstract void visitUnwind(Unwind unwind);
+    public abstract void visitLoopBegin(LoopBegin loopBegin);
+    public abstract void visitLoopEnd(LoopEnd loopEnd);
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java	Fri May 27 14:20:30 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java	Fri May 27 17:48:28 2011 +0200
@@ -531,4 +531,20 @@
         lir.jump(getLIRBlock(x.otherSuccessor()));
     }
 
+    @Override
+    public void visitLoopBegin(LoopBegin x) {
+        visitMerge(x);
+    }
+
+    @Override
+    public void visitLoopEnd(LoopEnd x) {
+        setNoResult(x);
+
+        // emit phi-instruction moves after safepoint since this simplifies
+        // describing the state at the safepoint.
+
+        moveToPhi();
+        lir.jump(getLIRBlock(x.loopBegin()));
+    }
+
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java	Fri May 27 14:20:30 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java	Fri May 27 17:48:28 2011 +0200
@@ -371,7 +371,11 @@
                         }
                     }
 
-                    assert phi.valueCount() == block.predecessors().size() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.predecessors().size();
+                    if (block instanceof LoopBegin) {
+//                        assert phi.valueCount() == ((LoopBegin) block).loopEnd().predecessors().size() + 1 : "loop, valueCount=" + phi.valueCount() + " predSize= " + ((LoopBegin) block).loopEnd().predecessors().size();
+                    } else {
+                        assert phi.valueCount() == block.predecessors().size() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.predecessors().size();
+                    }
                }
             }
         }
--- a/graal/GraalGraphviz/src/com/oracle/graal/graph/vis/GraphvizPrinter.java	Fri May 27 14:20:30 2011 +0200
+++ b/graal/GraalGraphviz/src/com/oracle/graal/graph/vis/GraphvizPrinter.java	Fri May 27 17:48:28 2011 +0200
@@ -25,6 +25,7 @@
 import java.awt.Color;
 import java.io.OutputStream;
 import java.io.PrintStream;
+import java.util.HashMap;
 import java.util.HashSet;
 
 import com.oracle.graal.graph.Graph;
@@ -46,6 +47,7 @@
 
     private final PrintStream out;
     private final HashSet<Class<?>> omittedClasses = new HashSet<Class<?>>();
+    private final HashMap<Class<?>, String> classColors = new HashMap<Class<?>, String>();
 
     /**
      * Creates a new {@link GraphvizPrinter} that writes to the specified output stream.
@@ -58,6 +60,10 @@
         omittedClasses.add(clazz);
     }
 
+    public void addClassColor(Class<?> clazz, String color) {
+        classColors.put(clazz, color);
+    }
+
     /**
      * Opens a graph with the specified title (label). Call this before printing any nodes, but not more than once
      * without calling {@link #end()} first.
@@ -104,10 +110,12 @@
         NodeArray inputs = node.inputs();
         NodeArray successors = node.successors();
 
+        String color = classColors.get(node.getClass());
+
         if (shortNames) {
-            printNode(name, node.shortName(), inputs.size(), successors.size());
+            printNode(name, node.id(), excapeLabel(node.shortName()), color, inputs.size(), successors.size());
         } else {
-            printNode(name, node.toString(), inputs.size(), successors.size());
+            printNode(name, node.id(), excapeLabel(node.toString()), color, inputs.size(), successors.size());
         }
 
         for (int i = 0; i < successors.size(); ++i) {
@@ -128,8 +136,8 @@
         }
     }
 
-    private void printNode(String name, String label, int ninputs, int nsuccessors) {
-        int minWidth = Math.min(label.length() / 3, 10);
+    private void printNode(String name, Number number, String label, String color, int ninputs, int nsuccessors) {
+        int minWidth = Math.min(1 + label.length() / 3, 10);
         minWidth = Math.max(minWidth, Math.max(ninputs + 1, nsuccessors + 1));
         out.println(name + "  [shape=plaintext,");
         out.println("   label=< <TABLE BORDER=\"0\" CELLSPACING=\"0\"><TR>");
@@ -144,11 +152,11 @@
             printPort("in" + i, "lightgrey");
         }
 
-        label = label.replace("&", "&amp;");
-        label = label.replace("<", "&lt;");
-        label = label.replace(">", "&gt;");
-        label = label.replace("\"", "&quot;");
-        out.println("    </TR><TR><TD BORDER=\"1\" COLSPAN=\"" + minWidth + "\" BGCOLOR=\"" + NODE_BGCOLOR_STRING + "\">" + label + "</TD></TR><TR>");
+        if (number != null) {
+            label = "<FONT POINT-SIZE=\"8\">" + number + "</FONT> " + label;
+        }
+
+        out.println("    </TR><TR><TD BORDER=\"1\" COLSPAN=\"" + minWidth + "\" BGCOLOR=\"" + (color != null ? color : NODE_BGCOLOR_STRING) + "\">" + label + "</TD></TR><TR>");
 
         for (int i = 0; i < nsuccessors; i++) {
             printPort("succ" + i, "rosybrown1");
@@ -163,6 +171,14 @@
         out.println("    </TR></TABLE>>]; ");
     }
 
+    private static String excapeLabel(String label) {
+        label = label.replace("&", "&amp;");
+        label = label.replace("<", "&lt;");
+        label = label.replace(">", "&gt;");
+        label = label.replace("\"", "&quot;");
+        return label;
+    }
+
     private void printPort(String name, String color) {
         out.print("    <TD CELLPADDING=\"0\" WIDTH=\"15\"><TABLE BORDER=\"0\" CELLSPACING=\"2\" CELLPADDING=\"0\"><TR><TD WIDTH=\"15\" HEIGHT=\"5\" PORT=\"");
         out.print(name);
@@ -176,7 +192,7 @@
     }
 
     private void printControlEdge(int from, int fromPort, int to) {
-        out.println("n" + from + ":succ" + fromPort + " -> n" + to + ":predecessors:n [color=red, weight=2];");
+        out.println("n" + from + ":succ" + fromPort + ":s -> n" + to + ":predecessors:n [color=red, weight=2];");
     }
 
     private void printDataEdge(int from, int fromPort, int to) {
--- a/src/share/vm/compiler/compilerOracle.cpp	Fri May 27 14:20:30 2011 +0200
+++ b/src/share/vm/compiler/compilerOracle.cpp	Fri May 27 17:48:28 2011 +0200
@@ -471,7 +471,7 @@
   line += bytes_read;
 
   if (command == UnknownCommand) {
-    tty->print_cr("CompilerOracle: unrecognized line");
+    tty->print_cr("CompilerOracle: UnknownCommand");
     tty->print_cr("  \"%s\"", original_line);
     return;
   }