changeset 2871:d704eb526603

Merge.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 08 Jun 2011 08:31:38 +0200
parents 9075634c8d11 (current diff) fc75fd3fa5e4 (diff)
children 0341b6424579
files
diffstat 34 files changed, 1110 insertions(+), 302 deletions(-) [+]
line wrap: on
line diff
--- a/graal/GraalCompiler/src/com/oracle/max/graal/opt/CanonicalizerPhase.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/oracle/max/graal/opt/CanonicalizerPhase.java	Wed Jun 08 08:31:38 2011 +0200
@@ -22,15 +22,47 @@
  */
 package com.oracle.max.graal.opt;
 
+import java.util.*;
+
 import com.oracle.graal.graph.*;
+import com.sun.c1x.*;
 
 public class CanonicalizerPhase extends Phase {
 
 
     @Override
     protected void run(Graph graph) {
-        // TODO Auto-generated method stub
+        NodeBitMap visited = graph.createNodeBitMap();
+        List<Node> nodes = new ArrayList<Node>(graph.getNodes());
+        for (Node n : nodes) {
+            if (n == null) {
+                continue;
+            }
+            if (!visited.isMarked(n)) {
+                this.canonicalize(n, visited);
+            }
+        }
+    }
 
+    private void canonicalize(Node n, NodeBitMap visited) {
+        visited.mark(n);
+        for (Node input : n.inputs()) {
+            if (input == null) {
+                continue;
+            }
+            if (!visited.isNew(input) && !visited.isMarked(input)) {
+                canonicalize(input, visited);
+            }
+        }
+
+        CanonicalizerOp op = n.lookup(CanonicalizerOp.class);
+        if (op != null) {
+            Node canonical = op.canonical(n);
+            if (canonical != n) {
+                n.replace(canonical);
+                C1XMetrics.NodesCanonicalized++;
+            }
+        }
     }
 
     public interface CanonicalizerOp extends Op {
--- a/graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java	Wed Jun 08 08:31:38 2011 +0200
@@ -81,7 +81,7 @@
         return b;
     }
 
-    private static boolean isCFG(Node n) {
+    public static boolean isFixed(Node n) {
         return n != null && ((n instanceof FixedNode) || n == n.graph().start());
     }
 
@@ -95,7 +95,7 @@
         NodeIterator.iterate(EdgeType.SUCCESSORS, graph.start(), null, new NodeVisitor() {
             @Override
             public boolean visit(Node n) {
-                if (!isCFG(n)) {
+                if (!isFixed(n)) {
                     return false;
                 }
 
@@ -108,7 +108,7 @@
 
                 Node singlePred = null;
                 for (Node pred : n.predecessors()) {
-                    if (isCFG(pred)) {
+                    if (isFixed(pred)) {
                         if (singlePred == null) {
                             singlePred = pred;
                         } else {
@@ -141,7 +141,7 @@
         for (Node n : blockBeginNodes) {
             Block block = nodeToBlock.get(n);
             for (Node pred : n.predecessors()) {
-                if (isCFG(pred)) {
+                if (isFixed(pred)) {
                     Block predBlock = nodeToBlock.get(pred);
                     predBlock.addSuccessor(block);
                 }
@@ -229,7 +229,7 @@
             } else if (usage instanceof FrameState && ((FrameState) usage).block() != null) {
                 Merge merge = ((FrameState) usage).block();
                 for (Node pred : merge.predecessors()) {
-                    if (isCFG(pred)) {
+                    if (isFixed(pred)) {
                         block = getCommonDominator(block, nodeToBlock.get(pred));
                     }
                 }
@@ -437,7 +437,7 @@
         }
         int i = 0;
         for (Node s : n.successors()) {
-            if (isCFG(s)) {
+            if (isFixed(s)) {
                 i++;
             }
         }
@@ -450,7 +450,7 @@
         }
         int i = 0;
         for (Node s : n.predecessors()) {
-            if (isCFG(s)) {
+            if (isFixed(s)) {
                 i++;
             }
         }
--- a/graal/GraalCompiler/src/com/sun/c1x/C1XMetrics.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/C1XMetrics.java	Wed Jun 08 08:31:38 2011 +0200
@@ -62,6 +62,7 @@
     public static int UniqueValueIdsAssigned;
     public static int FrameStatesCreated;
     public static int FrameStateValuesCreated;
+    public static int NodesCanonicalized;
 
     public static void print() {
         printClassFields(C1XMetrics.class);
--- a/graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java	Wed Jun 08 08:31:38 2011 +0200
@@ -45,7 +45,7 @@
     public static int     MaximumInlineSize                  = 35;
     public static int     MaximumTrivialSize                 = 6;
     public static int     MaximumInlineLevel                 = 9;
-    public static int     MaximumRecursiveInlineLevel        = 1;
+    public static int     MaximumRecursiveInlineLevel        = 2;
     public static int     MaximumDesiredSize                 = 8000;
     public static int     MaximumShortLoopSize               = 5;
 
@@ -69,7 +69,7 @@
     // DOT output settings
     public static boolean PrintDOTGraphToFile                = ____;
     public static boolean PrintDOTGraphToPdf                 = ____;
-    public static boolean OmitDOTFrameStates                 = true;
+    public static boolean OmitDOTFrameStates                 = ____;
 
     // Ideal graph visualizer output settings
     public static int     PrintIdealGraphLevel               = 0;
@@ -92,6 +92,7 @@
     public static boolean TraceLIRVisit                      = ____;
     public static boolean TraceAssembler                     = ____;
     public static boolean TraceInlining                      = ____;
+    public static boolean TraceDeadCodeElimination           = ____;
     public static int     TraceBytecodeParserLevel           = 0;
     public static boolean QuietBailout                       = ____;
 
@@ -127,4 +128,6 @@
     // Assembler settings
     public static boolean CommentedAssembly                  = ____;
     public static boolean PrintLIRWithAssembly               = ____;
+
+    public static boolean OptCanonicalizer                   = true;
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java	Wed Jun 08 08:31:38 2011 +0200
@@ -1898,7 +1898,8 @@
                 values[valueIndex++] = monitorAddress;
                 assert frameRefMap != null;
                 CiStackSlot objectAddress = frameMap.toMonitorObjectStackAddress(i);
-                LIRDebugInfo.setBit(frameRefMap, objectAddress.index());
+//                LIRDebugInfo.setBit(frameRefMap, objectAddress.index());
+                frameRefMap.set(objectAddress.index());
             } else {
                 Value lock = state.lockAt(i);
                 if (lock.isConstant() && compilation.runtime.asJavaClass(lock.asConstant()) != null) {
--- a/graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinter.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinter.java	Wed Jun 08 08:31:38 2011 +0200
@@ -112,10 +112,15 @@
     public void print(Graph graph, String title, boolean shortNames) {
         stream.printf(" <graph name='%s'>%n", escape(title));
 
-        Schedule schedule = new Schedule(graph);
+        Schedule schedule = null;
+        try {
+            schedule = new Schedule(graph);
+        } catch (Throwable t) {
+            // nothing to do here...
+        }
 
         stream.println("  <nodes>");
-        List<Edge> edges = printNodes(graph.getNodes(), shortNames, schedule.getNodeToBlock());
+        List<Edge> edges = printNodes(graph.getNodes(), shortNames, schedule == null ? null : schedule.getNodeToBlock());
         stream.println("  </nodes>");
 
         stream.println("  <edges>");
@@ -125,10 +130,12 @@
         stream.println("  </edges>");
 
         stream.println("  <controlFlow>");
-        for (Block block : schedule.getBlocks()) {
-            printBlock(graph, block);
+        if (schedule != null) {
+            for (Block block : schedule.getBlocks()) {
+                printBlock(graph, block);
+            }
+            printNoBlock();
         }
-        printNoBlock();
         stream.println("  </controlFlow>");
 
         stream.println(" </graph>");
@@ -155,12 +162,14 @@
                 }
                 stream.printf("    <p name='name'>%s</p>%n", escape(name));
             }
-            Block block = nodeToBlock.get(node);
-            if (block != null) {
-                stream.printf("    <p name='block'>%d</p>%n", block.blockID());
-            } else {
-                stream.printf("    <p name='block'>noBlock</p>%n");
-                noBlockNodes.add(node);
+            if (nodeToBlock != null) {
+                Block block = nodeToBlock.get(node);
+                if (block != null) {
+                    stream.printf("    <p name='block'>%d</p>%n", block.blockID());
+                } else {
+                    stream.printf("    <p name='block'>noBlock</p>%n");
+                    noBlockNodes.add(node);
+                }
             }
             for (Entry<Object, Object> entry : props.entrySet()) {
                 String key = entry.getKey().toString();
--- a/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java	Wed Jun 08 08:31:38 2011 +0200
@@ -1377,7 +1377,7 @@
     }
 
     private CiValue operandForPhi(Phi phi) {
-        assert !phi.isDead();
+        assert !phi.isDead() : "dead phi: " + phi.id();
         if (phi.operand().isIllegal()) {
             // allocate a variable for this phi
             CiVariable operand = newVariable(phi.kind);
--- a/graal/GraalCompiler/src/com/sun/c1x/gen/PhiSimplifier.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/gen/PhiSimplifier.java	Wed Jun 08 08:31:38 2011 +0200
@@ -23,7 +23,6 @@
 package com.sun.c1x.gen;
 
 import com.oracle.graal.graph.*;
-import com.sun.c1x.graph.*;
 import com.sun.c1x.ir.*;
 
 /**
@@ -34,8 +33,7 @@
     private NodeBitMap visited;
     private NodeBitMap cannotSimplify;
 
-    public PhiSimplifier(IR ir) {
-        Graph graph = ir.compilation.graph;
+    public PhiSimplifier(Graph graph) {
         visited = graph.createNodeBitMap();
         cannotSimplify = graph.createNodeBitMap();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/DeadCodeElimination.java	Wed Jun 08 08:31:38 2011 +0200
@@ -0,0 +1,133 @@
+/*
+ * 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.graph;
+
+import com.oracle.graal.graph.*;
+import com.sun.c1x.*;
+import com.sun.c1x.gen.*;
+import com.sun.c1x.ir.*;
+
+
+public class DeadCodeElimination extends Phase {
+
+    private NodeBitMap alive;
+    private NodeWorklist worklist;
+    private Graph graph;
+
+    public int deletedNodeCount;
+
+    @Override
+    protected void run(Graph graph) {
+        this.graph = graph;
+        this.alive = graph.createNodeBitMap();
+        this.worklist = graph.createNodeWorklist();
+
+        worklist.add(graph.start());
+
+        iterateSuccessors();
+        disconnectCFGNodes();
+
+        iterateInputs();
+        disconnectNonCFGNodes();
+
+        deleteCFGNodes();
+        deleteNonCFGNodes();
+
+        new PhiSimplifier(graph);
+
+        if (C1XOptions.TraceDeadCodeElimination) {
+            System.out.printf("dead code elimination: deleted %d nodes\n", deletedNodeCount);
+        }
+    }
+
+    private static boolean isCFG(Node n) {
+        return n != null && ((n instanceof Instruction) || n == n.graph().start());
+    }
+
+    private void iterateSuccessors() {
+        for (Node current : worklist) {
+            for (Node successor : current.successors()) {
+                worklist.add(successor);
+            }
+        }
+    }
+
+    private void disconnectCFGNodes() {
+        for (Node node : graph.getNodes()) {
+            if (node != Node.Null && !worklist.isMarked(node) && isCFG(node)) {
+                // iterate backwards so that the predecessor indexes in removePhiPredecessor are correct
+                for (int i = node.successors().size() - 1; i >= 0; i--) {
+                    Node successor = node.successors().get(i);
+                    if (successor != Node.Null && worklist.isMarked(successor)) {
+                        if (successor instanceof Merge) {
+                            ((Merge) successor).removePhiPredecessor(node);
+                        }
+                    }
+                }
+                node.successors().clearAll();
+                node.inputs().clearAll();
+            }
+        }
+    }
+
+    private void deleteCFGNodes() {
+        for (Node node : graph.getNodes()) {
+            if (node != Node.Null && !worklist.isMarked(node) && isCFG(node)) {
+                node.delete();
+                deletedNodeCount++;
+            }
+        }
+    }
+
+    private void iterateInputs() {
+        for (Node node : graph.getNodes()) {
+            if (node != Node.Null && worklist.isMarked(node)) {
+                for (Node input : node.inputs()) {
+                    worklist.add(input);
+                }
+            }
+        }
+        for (Node current : worklist) {
+            for (Node input : current.inputs()) {
+                worklist.add(input);
+            }
+        }
+    }
+
+    private void disconnectNonCFGNodes() {
+        for (Node node : graph.getNodes()) {
+            if (node != Node.Null && !worklist.isMarked(node) && !isCFG(node)) {
+                node.inputs().clearAll();
+            }
+        }
+    }
+
+    private void deleteNonCFGNodes() {
+        for (Node node : graph.getNodes()) {
+            if (node != Node.Null && !worklist.isMarked(node) && !isCFG(node)) {
+                node.delete();
+                deletedNodeCount++;
+            }
+        }
+    }
+}
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Wed Jun 08 08:31:38 2011 +0200
@@ -121,9 +121,11 @@
 
     /**
      * Builds the graph for a the specified {@code IRScope}.
-     * @param scope the top IRScope
+     *
+     * @param createUnwind setting this to true will always generate an unwind block, even if there is no exception
+     *            handler and the method is not synchronized
      */
-    public void build() {
+    public void build(boolean createUnwind) {
         if (log != null) {
             log.println();
             log.println("Compiling " + method);
@@ -161,6 +163,10 @@
         } else {
             // 4B.1 simply finish the start block
             finishStartBlock(startBlock);
+
+            if (createUnwind) {
+                syncHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null);
+            }
         }
 
         // 5. SKIPPED: look for intrinsics
@@ -544,6 +550,9 @@
         Value yValue = frameState.pop(y);
         Value xValue = frameState.pop(x);
         Value result1 = append(new Arithmetic(opcode, result, xValue, yValue, isStrict(method.accessFlags()), canTrap, graph));
+        if (canTrap) {
+            append(new ValueAnchor(result1, graph));
+        }
         frameState.push(result, result1);
     }
 
@@ -554,7 +563,18 @@
     private void genShiftOp(CiKind kind, int opcode) {
         Value s = frameState.ipop();
         Value x = frameState.pop(kind);
-        frameState.push(kind, append(new Shift(opcode, x, s, graph)));
+        Shift v;
+        switch(opcode){
+            case ISHL:
+            case LSHL: v = new LeftShift(kind, x, s, graph); break;
+            case ISHR:
+            case LSHR: v = new RightShift(kind, x, s, graph); break;
+            case IUSHR:
+            case LUSHR: v = new UnsignedRightShift(kind, x, s, graph); break;
+            default:
+                throw new CiBailout("should not reach");
+        }
+        frameState.push(kind, append(v));
     }
 
     private void genLogicOp(CiKind kind, int opcode) {
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Wed Jun 08 08:31:38 2011 +0200
@@ -26,10 +26,10 @@
 import java.util.*;
 
 import com.oracle.graal.graph.*;
+import com.oracle.max.graal.opt.*;
 import com.oracle.max.graal.schedule.*;
 import com.sun.c1x.*;
 import com.sun.c1x.debug.*;
-import com.sun.c1x.gen.*;
 import com.sun.c1x.ir.*;
 import com.sun.c1x.lir.*;
 import com.sun.c1x.observer.*;
@@ -83,16 +83,12 @@
             C1XTimers.HIR_OPTIMIZE.start();
         }
 
-        new PhiSimplifier(this);
+        Graph graph = compilation.graph;
 
-//        Graph newGraph = new Graph();
-//        HashMap<Node, Node> replacement = new HashMap<Node, Node>();
-//        replacement.put(compilation.graph.start(), newGraph.start());
-//        replacement.put(compilation.graph.end(), newGraph.end());
-//        newGraph.addDuplicate(compilation.graph.getNodes(), replacement);
-//        compilation.graph = newGraph;
-
-        Graph graph = compilation.graph;
+        if (C1XOptions.OptCanonicalizer) {
+            new CanonicalizerPhase().apply(graph);
+            verifyAndPrint("After canonicalization");
+        }
 
         // Split critical edges.
         List<Node> nodes = graph.getNodes();
@@ -102,7 +98,7 @@
                 for (int j = 0; j < n.successors().size(); ++j) {
                     Node succ = n.successors().get(j);
                     if (Schedule.truePredecessorCount(succ) > 1) {
-                        Anchor a = new Anchor(null, graph);
+                        Anchor a = new Anchor(graph);
                         a.successors().setAndClear(1, n, j);
                         n.successors().set(j, a);
                     }
@@ -164,54 +160,24 @@
 
     private void buildGraph() {
         // Graph builder must set the startBlock and the osrEntryBlock
-        new GraphBuilder(compilation, compilation.method, compilation.graph).build();
+        new GraphBuilder(compilation, compilation.method, compilation.graph).build(false);
+
+//        CompilerGraph duplicate = new CompilerGraph();
+//        Map<Node, Node> replacements = new HashMap<Node, Node>();
+//        replacements.put(compilation.graph.start(), duplicate.start());
+//        duplicate.addDuplicate(compilation.graph.getNodes(), replacements);
+//        compilation.graph = duplicate;
 
         verifyAndPrint("After graph building");
 
-            if (C1XOptions.Inline) {
-            List<Invoke> trivialInline = new ArrayList<Invoke>();
-            List<Invoke> deoptInline = new ArrayList<Invoke>();
-            List<RiMethod> deoptMethods = new ArrayList<RiMethod>();
-            for (Node node : compilation.graph.getNodes()) {
-                if (node instanceof Invoke) {
-                    Invoke invoke = (Invoke) node;
-                    RiMethod target = invoke.target;
-                    if (target.isResolved() && !Modifier.isNative(target.accessFlags())) {
-                        if (target.canBeStaticallyBound()) {
-                            trivialInline.add(invoke);
-                        } else {
-                            RiMethod concrete = invoke.target.holder().uniqueConcreteMethod(invoke.target);
-                            if (concrete != null) {
-                                deoptInline.add(invoke);
-                                deoptMethods.add(concrete);
-                            }
-                        }
-                    }
-                }
-            }
+        DeadCodeElimination dce = new DeadCodeElimination();
+        dce.apply(compilation.graph);
+        if (dce.deletedNodeCount > 0) {
+            verifyAndPrint("After dead code elimination");
+        }
 
-            int allowedInlinings = 50;
-            for (Invoke invoke : trivialInline) {
-                if (inlineMethod(invoke, invoke.target)) {
-                    if (--allowedInlinings <= 0) {
-                        break;
-                    }
-                }
-            }
-
-            for (int i = 0; i < deoptInline.size(); i++) {
-                Invoke invoke = deoptInline.get(i);
-                RiMethod method = deoptMethods.get(i);
-                if (inlineMethod(invoke, method)) {
-                    if (C1XOptions.TraceInlining) {
-                        System.out.println("registering concrete method assumption...");
-                    }
-                    compilation.assumptions.recordConcreteMethod(invoke.target, method);
-                    if (--allowedInlinings <= 0) {
-                        break;
-                    }
-                }
-            }
+        if (C1XOptions.Inline) {
+            new Inlining(compilation, this).apply(compilation.graph);
         }
 
         if (C1XOptions.PrintCompilation) {
@@ -219,177 +185,6 @@
         }
     }
 
-    private boolean inlineMethod(Invoke invoke, RiMethod method) {
-        String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
-
-        if (method.code().length > 50) {
-            if (C1XOptions.TraceInlining) {
-                System.out.println("not inlining " + name + " because of code size");
-            }
-            return false;
-        }
-
-        Instruction exceptionEdge = invoke.exceptionEdge();
-        if (exceptionEdge != null) {
-            if (C1XOptions.TraceInlining) {
-                System.out.println("not inlining " + name + " because of exceptionEdge");
-            }
-            return false;
-        }
-        if (!method.holder().isInitialized()) {
-            if (C1XOptions.TraceInlining) {
-                System.out.println("not inlining " + name + " because of non-initialized class");
-            }
-            return false;
-        }
-
-        if (C1XOptions.TraceInlining) {
-            System.out.println("building graph: " + name);
-        }
-        CompilerGraph graph = new CompilerGraph();
-        new GraphBuilder(compilation, method, graph).build();
-
-        boolean withReceiver = !Modifier.isStatic(method.accessFlags());
-
-        int argumentCount = method.signature().argumentCount(false);
-        Value[] parameters = new Value[argumentCount + (withReceiver ? 1 : 0)];
-        int slot = withReceiver ? 1 : 0;
-        int param = withReceiver ? 1 : 0;
-        for (int i = 0; i < argumentCount; i++) {
-            parameters[param++] = invoke.argument(slot);
-            slot += method.signature().argumentKindAt(i).sizeInSlots();
-        }
-        if (withReceiver) {
-            parameters[0] = invoke.argument(0);
-        }
-
-        HashMap<Node, Node> replacements = new HashMap<Node, Node>();
-        ArrayList<Node> nodes = new ArrayList<Node>();
-        ArrayList<Node> frameStates = new ArrayList<Node>();
-        Return returnNode = null;
-        Unwind unwindNode = null;
-        StartNode startNode = null;
-        boolean invokes = false;
-        for (Node node : graph.getNodes()) {
-            if (node != null) {
-                if (node instanceof StartNode) {
-                    startNode = (StartNode) node;
-                } else if (node instanceof Local) {
-                    replacements.put(node, parameters[((Local) node).index()]);
-                } else {
-                    nodes.add(node);
-                    if (node instanceof Return) {
-                        returnNode = (Return) node;
-                    } else if (node instanceof Unwind) {
-                        unwindNode = (Unwind) node;
-                    } else if (node instanceof FrameState) {
-                        frameStates.add(node);
-                    }
-                }
-            }
-        }
-        if (unwindNode != null) {
-            if (C1XOptions.TraceInlining) {
-                System.out.println("not inlining " + name + " because of unwind node");
-            }
-            return false;
-        }
-        if (invokes) {
-            if (C1XOptions.TraceInlining) {
-                System.out.println("not inlining " + name + " because of invokes");
-            }
-            return false;
-        }
-
-        if (C1XOptions.TraceInlining) {
-            System.out.println("inlining " + name + ": " + frameStates.size() + " frame states, " + nodes.size() + " nodes");
-        }
-
-        Instruction pred;
-        if (withReceiver) {
-            pred = new NullCheck(parameters[0], compilation.graph);
-        } else {
-            pred = new Merge(compilation.graph);
-        }
-        assert invoke.predecessors().size() == 1;
-        invoke.predecessors().get(0).successors().replace(invoke, pred);
-        replacements.put(startNode, pred);
-
-        Map<Node, Node> duplicates = compilation.graph.addDuplicate(nodes, replacements);
-
-        if (returnNode != null) {
-            List<Node> usages = new ArrayList<Node>(invoke.usages());
-            for (Node usage : usages) {
-                if (returnNode.result() instanceof Local) {
-                    usage.inputs().replace(invoke, replacements.get(returnNode.result()));
-                } else {
-                    usage.inputs().replace(invoke, duplicates.get(returnNode.result()));
-                }
-            }
-            Node returnDuplicate = duplicates.get(returnNode);
-            returnDuplicate.inputs().clearAll();
-
-            assert returnDuplicate.predecessors().size() == 1;
-            Node returnPred = returnDuplicate.predecessors().get(0);
-            int index = returnDuplicate.predecessorsIndex().get(0);
-            returnPred.successors().setAndClear(index, invoke, 0);
-
-            returnDuplicate.delete();
-        }
-        FrameState stateAfter = invoke.stateAfter();
-        if (frameStates.size() > 0) {
-            FrameState outerFrameState = stateAfter.duplicateModified(invoke.bci, invoke.kind);
-            for (Node frameState : frameStates) {
-                ((FrameState) duplicates.get(frameState)).setOuterFrameState(outerFrameState);
-            }
-        }
-
-        invoke.successors().clearAll();
-        invoke.inputs().clearAll();
-        invoke.delete();
-
-        stateAfter.delete();
-
-        deleteUnused(exceptionEdge);
-
-        verifyAndPrint("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false));
-        return true;
-    }
-
-    private void deleteUnused(Node node) {
-        if (node != null && node.predecessors().size() == 0) {
-            if (node instanceof ExceptionObject) {
-                Node successor = node.successors().get(0);
-                node.successors().clearAll();
-                if (successor instanceof ExceptionDispatch) {
-                    ExceptionDispatch dispatch = (ExceptionDispatch) successor;
-                    Node succ1 = dispatch.catchSuccessor();
-                    Node succ2 = dispatch.otherSuccessor();
-                    if (succ1 instanceof Merge) {
-                        ((Merge) succ1).removePhiPredecessor(dispatch);
-                    }
-                    if (succ2 instanceof Merge) {
-                        ((Merge) succ2).removePhiPredecessor(dispatch);
-                    }
-                    dispatch.successors().clearAll();
-                    deleteUnused(succ1);
-                    deleteUnused(succ2);
-                    dispatch.delete();
-                } else {
-                    assert successor instanceof Merge;
-                    System.out.println("succ: " + successor.successors().get(0));
-                    Node next = successor.successors().get(0);
-                    successor.successors().clearAll();
-                    deleteUnused(next);
-                    successor.delete();
-                }
-                node.delete();
-            } else if (node instanceof Unwind) {
-                node.delete();
-            }
-        }
-    }
-
     /**
      * Gets the linear scan ordering of blocks as a list.
      * @return the blocks in linear scan order
@@ -422,6 +217,17 @@
         }
     }
 
+    public void printGraph(String phase, Graph graph) {
+        if (C1XOptions.PrintHIR && !TTY.isSuppressed()) {
+            TTY.println(phase);
+            print(false);
+        }
+
+        if (compilation.compiler.isObserved()) {
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, phase, graph, true, false));
+        }
+    }
+
     public int numLoops() {
         return compilation.stats.loopCount;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/Inlining.java	Wed Jun 08 08:31:38 2011 +0200
@@ -0,0 +1,288 @@
+/*
+ * 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.graph;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.sun.c1x.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+
+public class Inlining extends Phase {
+
+    private final C1XCompilation compilation;
+    private final IR ir;
+
+    private final Queue<Invoke> invokes = new ArrayDeque<Invoke>();
+    private final Queue<RiMethod> methods = new ArrayDeque<RiMethod>();
+    private int inliningSize;
+
+    public Inlining(C1XCompilation compilation, IR ir) {
+        this.compilation = compilation;
+        this.ir = ir;
+    }
+
+    private void addToQueue(Invoke invoke, RiMethod method) {
+        invokes.add(invoke);
+        methods.add(method);
+        inliningSize += method.code().length;
+    }
+
+    @Override
+    protected void run(Graph graph) {
+        if (!C1XOptions.Inline) {
+            return;
+        }
+
+        inliningSize = compilation.method.code().length;
+        int iterations = C1XOptions.MaximumRecursiveInlineLevel;
+        do {
+            for (Node node : graph.getNodes()) {
+                if (node instanceof Invoke) {
+                    Invoke invoke = (Invoke) node;
+                    RiMethod target = invoke.target;
+                    if (!checkInliningConditions(invoke) || !target.isResolved() || Modifier.isNative(target.accessFlags())) {
+                        continue;
+                    }
+                    if (target.canBeStaticallyBound()) {
+                        if (checkInliningConditions(invoke.target)) {
+                            addToQueue(invoke, invoke.target);
+                        }
+                    } else {
+                        RiMethod concrete = invoke.target.holder().uniqueConcreteMethod(invoke.target);
+                        if (concrete != null && concrete.isResolved() && !Modifier.isNative(concrete.accessFlags())) {
+                            if (checkInliningConditions(concrete)) {
+                                if (C1XOptions.TraceInlining) {
+                                    System.out.println("registering concrete method assumption...");
+                                }
+                                compilation.assumptions.recordConcreteMethod(invoke.target, concrete);
+                                addToQueue(invoke, concrete);
+                            }
+                        }
+                    }
+                    if (inliningSize > C1XOptions.MaximumInstructionCount) {
+                        break;
+                    }
+                }
+            }
+
+            assert invokes.size() == methods.size();
+            if (invokes.isEmpty()) {
+                break;
+            }
+
+            Invoke invoke;
+            while ((invoke = invokes.poll()) != null) {
+                RiMethod method = methods.remove();
+                inlineMethod(invoke, method);
+            }
+            DeadCodeElimination dce = new DeadCodeElimination();
+            dce.apply(graph);
+            if (dce.deletedNodeCount > 0) {
+                ir.verifyAndPrint("After dead code elimination");
+            }
+            ir.verifyAndPrint("After inlining iteration");
+
+            if (inliningSize > C1XOptions.MaximumInstructionCount) {
+                if (C1XOptions.TraceInlining) {
+                    System.out.println("inlining stopped: MaximumInstructionCount reached");
+                }
+                break;
+            }
+        } while(--iterations > 0);
+    }
+
+    private boolean checkInliningConditions(Invoke invoke) {
+        String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", invoke.target, false);
+        if (invoke.predecessors().size() == 0) {
+            if (C1XOptions.TraceInlining) {
+                System.out.println("not inlining " + name + " because the invoke is dead code");
+            }
+            return false;
+        }
+        return true;
+    }
+
+    private boolean checkInliningConditions(RiMethod method) {
+        String name = null;
+        if (C1XOptions.TraceInlining) {
+            name = CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
+        }
+        if (method.code().length > C1XOptions.MaximumInlineSize) {
+            if (C1XOptions.TraceInlining) {
+                System.out.println("not inlining " + name + " because of code size");
+            }
+            return false;
+        }
+        if (!method.holder().isInitialized()) {
+            if (C1XOptions.TraceInlining) {
+                System.out.println("not inlining " + name + " because of non-initialized class");
+            }
+            return false;
+        }
+        return true;
+    }
+
+    private void inlineMethod(Invoke invoke, RiMethod method) {
+        String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
+        FrameState stateAfter = invoke.stateAfter();
+        Instruction exceptionEdge = invoke.exceptionEdge();
+
+        if (C1XOptions.TraceInlining) {
+            System.out.printf("Building graph for %s, locals: %d, stack: %d\n", name, method.maxLocals(), method.maxStackSize());
+        }
+
+        CompilerGraph graph = new CompilerGraph();
+        new GraphBuilder(compilation, method, graph).build(true);
+
+        boolean withReceiver = !Modifier.isStatic(method.accessFlags());
+
+        int argumentCount = method.signature().argumentCount(false);
+        Value[] parameters = new Value[argumentCount + (withReceiver ? 1 : 0)];
+        int slot = withReceiver ? 1 : 0;
+        int param = withReceiver ? 1 : 0;
+        for (int i = 0; i < argumentCount; i++) {
+            parameters[param++] = invoke.argument(slot);
+            slot += method.signature().argumentKindAt(i).sizeInSlots();
+        }
+        if (withReceiver) {
+            parameters[0] = invoke.argument(0);
+        }
+
+        HashMap<Node, Node> replacements = new HashMap<Node, Node>();
+        ArrayList<Node> nodes = new ArrayList<Node>();
+        ArrayList<Node> frameStates = new ArrayList<Node>();
+        Return returnNode = null;
+        Unwind unwindNode = null;
+        StartNode startNode = graph.start();
+        for (Node node : graph.getNodes()) {
+            if (node != null) {
+                if (node instanceof StartNode) {
+                    assert startNode == node;
+                } else if (node instanceof Local) {
+                    replacements.put(node, parameters[((Local) node).index()]);
+                } else {
+                    nodes.add(node);
+                    if (node instanceof Return) {
+                        returnNode = (Return) node;
+                    } else if (node instanceof Unwind) {
+                        unwindNode = (Unwind) node;
+                    } else if (node instanceof FrameState) {
+                        frameStates.add(node);
+                    }
+                }
+            }
+        }
+
+        if (C1XOptions.TraceInlining) {
+            ir.printGraph("Subgraph " + CiUtil.format("%H.%n(%p):%r", method, false), graph);
+            System.out.println("inlining " + name + ": " + frameStates.size() + " frame states, " + nodes.size() + " nodes");
+        }
+
+        assert invoke.predecessors().size() == 1 : "size: " + invoke.predecessors().size();
+        Instruction pred;
+        if (withReceiver) {
+            pred = new NullCheck(parameters[0], compilation.graph);
+        } else {
+            pred = new Merge(compilation.graph);
+        }
+        invoke.predecessors().get(0).successors().replace(invoke, pred);
+        replacements.put(startNode, pred);
+
+        Map<Node, Node> duplicates = compilation.graph.addDuplicate(nodes, replacements);
+
+        if (returnNode != null) {
+            List<Node> usages = new ArrayList<Node>(invoke.usages());
+            for (Node usage : usages) {
+                if (returnNode.result() instanceof Local) {
+                    usage.inputs().replace(invoke, replacements.get(returnNode.result()));
+                } else {
+                    usage.inputs().replace(invoke, duplicates.get(returnNode.result()));
+                }
+            }
+            Node returnDuplicate = duplicates.get(returnNode);
+            returnDuplicate.inputs().clearAll();
+
+            assert returnDuplicate.predecessors().size() == 1;
+            Node returnPred = returnDuplicate.predecessors().get(0);
+            int index = returnDuplicate.predecessorsIndex().get(0);
+            returnPred.successors().setAndClear(index, invoke, 0);
+            returnDuplicate.delete();
+        }
+
+//        if (invoke.next() instanceof Merge) {
+//            ((Merge) invoke.next()).removePhiPredecessor(invoke);
+//        }
+//        invoke.successors().clearAll();
+        invoke.inputs().clearAll();
+        invoke.setExceptionEdge(null);
+//        invoke.delete();
+
+
+        if (exceptionEdge != null) {
+            if (unwindNode != null) {
+                assert unwindNode.predecessors().size() == 1;
+                assert exceptionEdge.successors().size() == 1;
+                ExceptionObject obj = (ExceptionObject) exceptionEdge;
+
+                List<Node> usages = new ArrayList<Node>(obj.usages());
+                for (Node usage : usages) {
+                    if (replacements.containsKey(unwindNode.exception())) {
+                        usage.inputs().replace(obj, replacements.get(unwindNode.exception()));
+                    } else {
+                        usage.inputs().replace(obj, duplicates.get(unwindNode.exception()));
+                    }
+                }
+                Node unwindDuplicate = duplicates.get(unwindNode);
+                unwindDuplicate.inputs().clearAll();
+
+                assert unwindDuplicate.predecessors().size() == 1;
+                Node unwindPred = unwindDuplicate.predecessors().get(0);
+                int index = unwindDuplicate.predecessorsIndex().get(0);
+                unwindPred.successors().setAndClear(index, obj, 0);
+
+                obj.inputs().clearAll();
+                obj.delete();
+                unwindDuplicate.delete();
+
+            }
+        }
+
+        // adjust all frame states that were copied
+        if (frameStates.size() > 0) {
+            FrameState outerFrameState = stateAfter.duplicateModified(invoke.bci, invoke.kind);
+            for (Node frameState : frameStates) {
+                ((FrameState) duplicates.get(frameState)).setOuterFrameState(outerFrameState);
+            }
+        }
+
+        if (C1XOptions.TraceInlining) {
+            ir.verifyAndPrint("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false));
+        }
+    }
+}
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Anchor.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Anchor.java	Wed Jun 08 08:31:38 2011 +0200
@@ -27,7 +27,7 @@
 import com.sun.cri.ci.*;
 
 /**
- * The {@code Goto} instruction represents the end of a block with an unconditional jump to another block.
+ * The {@code Anchor} instruction represents the end of a block with an unconditional jump to another block.
  */
 public final class Anchor extends BlockEnd {
 
@@ -35,14 +35,11 @@
     private static final int SUCCESSOR_COUNT = 0;
 
     /**
-     * Constructs a new Goto instruction.
-     * @param succ the successor block of the goto
-     * @param stateAfter the frame state at the end of this block
+     * Constructs a new Anchor instruction.
      * @param graph
      */
-    public Anchor(Instruction succ, Graph graph) {
+    public Anchor(Graph graph) {
         super(CiKind.Illegal, 1, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        setBlockSuccessor(0, succ);
     }
 
     @Override
@@ -57,7 +54,7 @@
 
     @Override
     public Node copy(Graph into) {
-        Anchor x = new Anchor(null, into);
+        Anchor x = new Anchor(into);
         return x;
     }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/And.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/And.java	Wed Jun 08 08:31:38 2011 +0200
@@ -47,7 +47,7 @@
 
     @Override
     public Node copy(Graph into) {
-        And x = new And(kind, null, null, graph());
+        And x = new And(kind, null, null, into);
         return x;
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Deoptimize.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Deoptimize.java	Wed Jun 08 08:31:38 2011 +0200
@@ -57,7 +57,7 @@
 
     @Override
     public String shortName() {
-        return "Deopt " + message;
+        return message == null ? "Deopt " : "Deopt " + message;
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/LeftShift.java	Wed Jun 08 08:31:38 2011 +0200
@@ -0,0 +1,54 @@
+/*
+ * 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.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class LeftShift extends Shift {
+
+    /**
+     * @param opcode
+     * @param kind
+     * @param x
+     * @param y
+     * @param graph
+     */
+    public LeftShift(CiKind kind, Value x, Value y, Graph graph) {
+        super(kind, kind == CiKind.Int ? Bytecodes.ISHL : Bytecodes.LSHL, x, y, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return "<<";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        LeftShift ls = new LeftShift(kind, null, null, graph());
+        return ls;
+    }
+
+}
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java	Wed Jun 08 08:31:38 2011 +0200
@@ -267,15 +267,15 @@
         return x;
     }
 
-    public void removePhiPredecessor(ExceptionDispatch successor) {
-        int predIndex = predecessors().indexOf(successor);
+    public void removePhiPredecessor(Node pred) {
+        int predIndex = predecessors().lastIndexOf(pred);
         assert predIndex != -1;
 
         for (Node usage : usages()) {
             if (usage instanceof Phi) {
                 Phi phi = (Phi) usage;
-                assert phi.valueCount() == predecessors().size();
-                phi.removeInput(predIndex + 1);
+//                assert phi.valueCount() == predecessors().size();
+                phi.removeInput(predIndex);
             }
         }
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Or.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Or.java	Wed Jun 08 08:31:38 2011 +0200
@@ -23,6 +23,7 @@
 package com.sun.c1x.ir;
 
 import com.oracle.graal.graph.*;
+import com.oracle.max.graal.opt.CanonicalizerPhase.CanonicalizerOp;
 import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
 
@@ -31,6 +32,7 @@
  *
  */
 public final class Or extends Logic {
+    private static final OrCanonicalizerOp CANONICALIZER = new OrCanonicalizerOp();
 
     /**
      * @param opcode
@@ -50,8 +52,65 @@
 
     @Override
     public Node copy(Graph into) {
-        Or x = new Or(kind, null, null, graph());
+        Or x = new Or(kind, null, null, into);
         return x;
     }
 
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class OrCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            assert node instanceof Or;
+            Or or = (Or) node;
+            CiKind kind = or.kind;
+            Graph graph = or.graph();
+            Value x = or.x();
+            Value y = or.y();
+            if (x == y) {
+                return x;
+            }
+            if (x.isConstant() && !y.isConstant()) {
+                or.swapOperands();
+                Value t = y;
+                y = x;
+                x = t;
+            }
+            if (x.isConstant()) {
+                if (kind == CiKind.Int) {
+                    return Constant.forInt(x.asConstant().asInt() | y.asConstant().asInt(), graph);
+                } else {
+                    assert kind == CiKind.Long;
+                    return Constant.forLong(x.asConstant().asLong() | y.asConstant().asLong(), graph);
+                }
+            } else if (y.isConstant()) {
+                if (kind == CiKind.Int) {
+                    int c = y.asConstant().asInt();
+                    if (c == -1) {
+                        return Constant.forInt(-1, graph);
+                    }
+                    if (c == 0) {
+                        return x;
+                    }
+                } else {
+                    assert kind == CiKind.Long;
+                    long c = y.asConstant().asLong();
+                    if (c == -1) {
+                        return Constant.forLong(-1, graph);
+                    }
+                    if (c == 0) {
+                        return x;
+                    }
+                }
+            }
+            return or;
+        }
+    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java	Wed Jun 08 08:31:38 2011 +0200
@@ -78,7 +78,7 @@
     public Phi(CiKind kind, Merge block, int maxValues, Graph graph) {
         super(kind, INPUT_COUNT + maxValues, SUCCESSOR_COUNT, graph);
         this.maxValues = maxValues;
-        usedInputCount = 1;
+        usedInputCount = 0;
         setBlock(block);
     }
 
@@ -89,7 +89,11 @@
      * @return the instruction that produced the value in the i'th predecessor
      */
     public Value valueAt(int i) {
-        return (Value) inputs().get(i + INPUT_COUNT);
+        return (Value) inputs().get(INPUT_COUNT + i);
+    }
+
+    public Node setValueAt(int i, Node x) {
+        return inputs().set(INPUT_COUNT + i, x);
     }
 
     /**
@@ -97,7 +101,7 @@
      * @return the number of inputs in this phi
      */
     public int valueCount() {
-        return usedInputCount - 1;
+        return usedInputCount;
     }
 
     @Override
@@ -119,11 +123,11 @@
     @Override
     public void print(LogStream out) {
         out.print("phi function (");
-        for (int i = 0; i < inputs().size(); ++i) {
+        for (int i = 0; i < valueCount(); ++i) {
             if (i != 0) {
                 out.print(' ');
             }
-            out.print((Value) inputs().get(i));
+            out.print(valueAt(i));
         }
         out.print(')');
     }
@@ -143,23 +147,24 @@
     public Phi addInput(Node y) {
         assert !this.isDeleted() && !y.isDeleted();
         Phi phi = this;
-        if (usedInputCount == inputs().size()) {
-            phi = new Phi(kind, block(), usedInputCount * 2, graph());
+        if (usedInputCount == maxValues) {
+            phi = new Phi(kind, block(), maxValues * 2, graph());
             for (int i = 0; i < valueCount(); ++i) {
                 phi.addInput(valueAt(i));
             }
             phi.addInput(y);
             this.replace(phi);
         } else {
-            phi.inputs().set(usedInputCount++, y);
+            setValueAt(usedInputCount++, y);
         }
         return phi;
     }
 
     public void removeInput(int index) {
-        inputs().set(index, null);
-        for (int i = index + 1; i < usedInputCount; ++i) {
-            inputs().set(i - 1, inputs().get(i));
+        assert index < valueCount() : "index: " + index + ", valueCount: " + valueCount() + "@phi " + id();
+        setValueAt(index, Node.Null);
+        for (int i = index + 1; i < valueCount(); ++i) {
+            setValueAt(i - 1, valueAt(i));
         }
         usedInputCount--;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/RightShift.java	Wed Jun 08 08:31:38 2011 +0200
@@ -0,0 +1,54 @@
+/*
+ * 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.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class RightShift extends Shift {
+
+    /**
+     * @param opcode
+     * @param kind
+     * @param x
+     * @param y
+     * @param graph
+     */
+    public RightShift(CiKind kind, Value x, Value y, Graph graph) {
+        super(kind, kind == CiKind.Int ? Bytecodes.ISHR : Bytecodes.LSHR, x, y, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return ">>";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        RightShift rs = new RightShift(kind, null, null, graph());
+        return rs;
+    }
+
+}
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Shift.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Shift.java	Wed Jun 08 08:31:38 2011 +0200
@@ -24,13 +24,12 @@
 
 import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
-import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
 
 /**
  * The {@code ShiftOp} class represents shift operations.
  */
-public final class Shift extends Binary {
+public abstract class Shift extends Binary {
 
     private static final int INPUT_COUNT = 0;
     private static final int SUCCESSOR_COUNT = 0;
@@ -41,12 +40,8 @@
      * @param x the first input value
      * @param y the second input value
      */
-    public Shift(int opcode, Value x, Value y, Graph graph) {
-        super(x.kind, opcode, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-    }
-
-    private Shift(CiKind kind, int opcode, Graph graph) {
-        super(kind, opcode, null, null, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    public Shift(CiKind kind, int opcode, Value x, Value y, Graph graph) {
+        super(kind, opcode, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
     @Override
@@ -56,12 +51,9 @@
 
     @Override
     public void print(LogStream out) {
-        out.print(x()).print(' ').print(Bytecodes.operator(opcode)).print(' ').print(y());
+        out.print(x()).print(' ').print(this.shortName()).print(' ').print(y());
     }
 
     @Override
-    public Node copy(Graph into) {
-        Shift x = new Shift(kind, opcode, into);
-        return x;
-    }
+    public abstract String shortName();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/UnsignedRightShift.java	Wed Jun 08 08:31:38 2011 +0200
@@ -0,0 +1,54 @@
+/*
+ * 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.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class UnsignedRightShift extends Shift {
+
+    /**
+     * @param opcode
+     * @param kind
+     * @param x
+     * @param y
+     * @param graph
+     */
+    public UnsignedRightShift(CiKind kind, Value x, Value y, Graph graph) {
+        super(kind, kind == CiKind.Int ? Bytecodes.IUSHR : Bytecodes.LUSHR, x, y, graph);
+    }
+
+    @Override
+    public String shortName() {
+        return ">>>";
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        UnsignedRightShift x = new UnsignedRightShift(kind, null, null, graph());
+        return x;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ValueAnchor.java	Wed Jun 08 08:31:38 2011 +0200
@@ -0,0 +1,85 @@
+/*
+ * 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.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The ValueAnchor instruction keeps non-CFG nodes above a certain point in the graph.
+ */
+public final class ValueAnchor extends Instruction {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_OBJECT = 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 that should be scheduled before this anchor.
+     */
+     public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public Value setObject(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    /**
+     * Constructs a new Anchor instruction.
+     * @param succ the successor block of the anchor
+     * @param graph
+     */
+    public ValueAnchor(Value object, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setObject(object);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitValueAnchor(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("value_anchor ").print(object());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        ValueAnchor x = new ValueAnchor(null, into);
+        return x;
+    }
+}
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java	Wed Jun 08 08:31:38 2011 +0200
@@ -71,4 +71,5 @@
     public abstract void visitUnwind(Unwind unwind);
     public abstract void visitLoopBegin(LoopBegin loopBegin);
     public abstract void visitLoopEnd(LoopEnd loopEnd);
+    public abstract void visitValueAnchor(ValueAnchor valueAnchor);
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Xor.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Xor.java	Wed Jun 08 08:31:38 2011 +0200
@@ -23,10 +23,12 @@
 package com.sun.c1x.ir;
 
 import com.oracle.graal.graph.*;
+import com.oracle.max.graal.opt.CanonicalizerPhase.CanonicalizerOp;
 import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
 
 public final class Xor extends Logic {
+    private static final XorCanonicalizerOp CANONICALIZER = new XorCanonicalizerOp();
 
     /**
      * @param opcode
@@ -46,8 +48,64 @@
 
     @Override
     public Node copy(Graph into) {
-        Xor x = new Xor(kind, null, null, graph());
+        Xor x = new Xor(kind, null, null, into);
         return x;
     }
 
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == CanonicalizerOp.class) {
+            return (T) CANONICALIZER;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static class XorCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            assert node instanceof Xor;
+            Xor xor = (Xor) node;
+            CiKind kind = xor.kind;
+            Graph graph = xor.graph();
+            Value x = xor.x();
+            Value y = xor.y();
+            if (x == y) {
+                if (kind == CiKind.Int) {
+                    return Constant.forInt(0, graph);
+                } else {
+                    assert kind == CiKind.Long;
+                    return Constant.forLong(0L, graph);
+                }
+            }
+            if (x.isConstant() && !y.isConstant()) {
+                xor.swapOperands();
+                Value t = y;
+                y = x;
+                x = t;
+            }
+            if (x.isConstant()) {
+                if (kind == CiKind.Int) {
+                    return Constant.forInt(x.asConstant().asInt() ^ y.asConstant().asInt(), graph);
+                } else {
+                    assert kind == CiKind.Long;
+                    return Constant.forLong(x.asConstant().asLong() ^ y.asConstant().asLong(), graph);
+                }
+            } else if (y.isConstant()) {
+                if (kind == CiKind.Int) {
+                    int c = y.asConstant().asInt();
+                    if (c == 0) {
+                        return x;
+                    }
+                } else {
+                    assert kind == CiKind.Long;
+                    long c = y.asConstant().asLong();
+                    if (c == 0) {
+                        return x;
+                    }
+                }
+            }
+            return xor;
+        }
+    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java	Wed Jun 08 08:31:38 2011 +0200
@@ -551,4 +551,9 @@
         lir.jump(getLIRBlock(x.loopBegin()));
     }
 
+    @Override
+    public void visitValueAnchor(ValueAnchor valueAnchor) {
+        // nothing to do for ValueAnchors
+    }
+
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java	Wed Jun 08 08:31:38 2011 +0200
@@ -49,7 +49,9 @@
         this.method = method;
         this.graph = graph;
         this.locals = new Value[method.maxLocals()];
-        this.stack = new Value[method.maxStackSize()];
+        // we always need at least one stack slot (for exceptions)
+        int stackSize = Math.max(1, method.maxStackSize());
+        this.stack = new Value[stackSize];
 
         int javaIndex = 0;
         int index = 0;
@@ -81,8 +83,8 @@
     }
 
     public void initializeFrom(FrameState other) {
-        assert locals.length == other.localsSize();
-        assert stack.length >= other.stackSize();
+        assert locals.length == other.localsSize() : "expected: " + locals.length + ", actual: " + other.localsSize();
+        assert stack.length >= other.stackSize() : "expected: <=" + stack.length + ", actual: " + other.stackSize();
 
         this.stackIndex = other.stackSize();
         for (int i = 0; i < other.localsSize(); i++) {
--- a/graal/GraalGraph/src/com/oracle/graal/graph/Graph.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalGraph/src/com/oracle/graal/graph/Graph.java	Wed Jun 08 08:31:38 2011 +0200
@@ -36,6 +36,14 @@
     private final StartNode start;
     int nextId;
 
+    static int nextGraphId = 0;
+    int id = nextGraphId++;
+
+    @Override
+    public String toString() {
+        return "Graph " + id;
+    }
+
     public Graph() {
         nodes = new ArrayList<Node>();
         start = new StartNode(this);
@@ -67,6 +75,10 @@
         return new NodeMap<T>(this);
     }
 
+    public NodeWorklist createNodeWorklist() {
+        return new NodeWorklist(this);
+    }
+
     public Map<Node, Node> addDuplicate(Collection<Node> nodes, Map<Node, Node> replacements) {
         Map<Node, Node> newNodes = new HashMap<Node, Node>();
         // create node duplicates
--- a/graal/GraalGraph/src/com/oracle/graal/graph/Node.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalGraph/src/com/oracle/graal/graph/Node.java	Wed Jun 08 08:31:38 2011 +0200
@@ -118,7 +118,7 @@
 
     public void delete() {
         assert !isDeleted();
-        assert usages.size() == 0 && predecessors.size() == 0 : "usages: " + usages.size() + ", predecessors: " + predecessors().size();
+        assert usages.size() == 0 && predecessors.size() == 0 : "id: " + id + ", usages: " + usages.size() + ", predecessors: " + predecessors().size();
         assert predecessorsIndex.size() == 0;
         for (int i = 0; i < inputs.size(); ++i) {
             inputs.set(i, Null);
--- a/graal/GraalGraph/src/com/oracle/graal/graph/NodeBitMap.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalGraph/src/com/oracle/graal/graph/NodeBitMap.java	Wed Jun 08 08:31:38 2011 +0200
@@ -35,6 +35,10 @@
         bitMap = new CiBitMap(graph.nextId);
     }
 
+    public Graph graph() {
+        return graph;
+    }
+
     public boolean setIntersect(NodeBitMap other) {
         return bitMap.setIntersect(other.bitMap);
     }
@@ -48,6 +52,10 @@
         return bitMap.get(node.id());
     }
 
+    public boolean isNew(Node node) {
+        return node.id() >= bitMap.size();
+    }
+
     public void mark(Node node) {
         check(node);
         bitMap.set(node.id());
@@ -60,7 +68,7 @@
 
     private void check(Node node) {
         assert node.graph == graph : "this node is not part of the graph";
-        assert node.id() < bitMap.size() : "this node (" + node.id() + ") was added to the graph after creating the node bitmap (" + bitMap.length() + ")";
+        assert !isNew(node) : "this node (" + node.id() + ") was added to the graph after creating the node bitmap (" + bitMap.length() + ")";
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalGraph/src/com/oracle/graal/graph/NodeWorklist.java	Wed Jun 08 08:31:38 2011 +0200
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2011, 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.graph;
+
+import java.util.ArrayDeque;
+import java.util.Iterator;
+import java.util.Queue;
+
+
+public class NodeWorklist implements Iterable<Node> {
+    private final NodeBitMap visited;
+    private final Queue<Node> worklist;
+
+    NodeWorklist(Graph graph) {
+        visited = graph.createNodeBitMap();
+        worklist = new ArrayDeque<Node>();
+    }
+
+    public void add(Node node) {
+        if (node != null && !visited.isMarked(node)) {
+            visited.mark(node);
+            worklist.add(node);
+        }
+    }
+
+    public boolean isMarked(Node node) {
+        return visited.isMarked(node);
+    }
+
+    private static class QueueConsumingIterator implements Iterator<Node> {
+        private final Queue<Node> queue;
+
+        public QueueConsumingIterator(Queue<Node> queue) {
+            this.queue = queue;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return !queue.isEmpty();
+        }
+
+        @Override
+        public Node next() {
+            return queue.remove();
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    @Override
+    public Iterator<Node> iterator() {
+        return new QueueConsumingIterator(worklist);
+    }
+
+    private static class UnmarkedNodeIterator implements Iterator<Node> {
+        private final NodeBitMap visited;
+        private Iterator<Node> nodes;
+        private Node nextNode;
+
+        public UnmarkedNodeIterator(NodeBitMap visited, Iterator<Node> nodes) {
+            this.visited = visited;
+            this.nodes = nodes;
+            forward();
+        }
+
+        private void forward() {
+            do {
+                if (!nodes.hasNext()) {
+                    nextNode = null;
+                    return;
+                }
+                nextNode = nodes.next();
+            } while (visited.isMarked(nextNode));
+        }
+
+        @Override
+        public boolean hasNext() {
+            return nextNode != null;
+        }
+
+        @Override
+        public Node next() {
+            try {
+                return nextNode;
+            } finally {
+                forward();
+            }
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+    }
+
+    public Iterable<Node> unmarkedNodes() {
+        return new Iterable<Node>() {
+            @Override
+            public Iterator<Node> iterator() {
+                return new UnmarkedNodeIterator(visited, visited.graph().getNodes().iterator());
+            }
+        };
+    }
+}
--- a/graal/GraalGraph/src/com/oracle/graal/graph/Op.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalGraph/src/com/oracle/graal/graph/Op.java	Wed Jun 08 08:31:38 2011 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
--- a/graal/GraalRuntime/src/com/oracle/graal/runtime/VMExitsNative.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/graal/GraalRuntime/src/com/oracle/graal/runtime/VMExitsNative.java	Wed Jun 08 08:31:38 2011 +0200
@@ -112,7 +112,7 @@
         } catch (Throwable t) {
             StringWriter out = new StringWriter();
             t.printStackTrace(new PrintWriter(out));
-            TTY.println("Compilation interrupted:\n" + out.toString());
+            TTY.println("Compilation interrupted: (" + name + ")\n" + out.toString());
             throw t;
         }
     }
--- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java	Tue Jun 07 16:34:38 2011 +0200
+++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java	Wed Jun 08 08:31:38 2011 +0200
@@ -542,7 +542,10 @@
 
         for (Node n : nodes) {
             InputNode inputNode = n.inputNode;
-            if (inputNode.getProperties().get("name").equals("Root")) {
+            if(inputNode.getProperties().get("name") == null) {
+                System.out.println("NO name !! " + inputNode);
+            }
+            if (inputNode != null && inputNode.getProperties().get("name") != null && inputNode.getProperties().get("name").equals("Root")) {
                 return n;
             } else if (inputNode.getId() == 0) {
                 // use as fallback in case no root node is found