changeset 2919:5429750cb94c

Merge
author Gilles Duboscq <gilles.duboscq@oracle.com>
date Thu, 09 Jun 2011 11:30:58 +0200
parents e7ba2bad98fb (current diff) c3faf3b842bb (diff)
children a6d0743f3380 44f7447e2f6d
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeWorklist.java
diffstat 17 files changed, 381 insertions(+), 277 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Wed Jun 08 22:41:16 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Thu Jun 09 11:30:58 2011 +0200
@@ -214,7 +214,11 @@
             if (GraalOptions.BailoutOnException) {
                 return new CiResult(null, new CiBailout("Exception while compiling: " + method, t), stats);
             } else {
-                throw new RuntimeException(t);
+                if (t instanceof RuntimeException) {
+                    throw (RuntimeException) t;
+                } else {
+                    throw new RuntimeException(t);
+                }
             }
         } finally {
             if (compiler.isObserved()) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Wed Jun 08 22:41:16 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Thu Jun 09 11:30:58 2011 +0200
@@ -834,11 +834,11 @@
 
                 if (instr instanceof Phi) {
                     Phi phi = (Phi) instr;
-                    TTY.println("phi block begin: " + phi.block());
-                    TTY.println("pred count on blockbegin: " + phi.block().predecessors().size());
+                    TTY.println("phi block begin: " + phi.merge());
+                    TTY.println("pred count on blockbegin: " + phi.merge().predecessors().size());
                     TTY.println("phi values: " + phi.valueCount());
                     TTY.println("phi block preds:");
-                    for (Node n : phi.block().predecessors()) {
+                    for (Node n : phi.merge().predecessors()) {
                         TTY.println(n.toString());
                     }
                 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Wed Jun 08 22:41:16 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Thu Jun 09 11:30:58 2011 +0200
@@ -135,8 +135,8 @@
             for (Block block : schedule.getBlocks()) {
                 printBlock(graph, block);
             }
-            printNoBlock();
         }
+        printNoBlock();
         stream.println("  </controlFlow>");
 
         stream.println(" </graph>");
@@ -163,14 +163,12 @@
                 }
                 stream.printf("    <p name='name'>%s</p>%n", escape(name));
             }
-            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);
-                }
+            Block block = nodeToBlock == null ? null : 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();
@@ -220,36 +218,38 @@
         stream.printf("    <nodes>%n");
 
         ArrayList<Node> nodes = new ArrayList<Node>(block.getInstructions());
-        // if this is the first block: add all locals to this block
-        if (nodes.get(0) == graph.start()) {
-            for (Node node : graph.getNodes()) {
-                if (node instanceof Local) {
-                    nodes.add(node);
-                }
-            }
-        }
-
-        // add all framestates and phis to their blocks
-        for (Node node : block.getInstructions()) {
-            if (node instanceof Instruction && ((Instruction) node).stateAfter() != null) {
-                nodes.add(((Instruction) node).stateAfter());
-            }
-            if (node instanceof Merge) {
-                Merge merge = (Merge) node;
-                if (merge.stateBefore() != null) {
-                    nodes.add(merge.stateBefore());
-                }
-                for (Node usage : merge.usages()) {
-                    if (usage instanceof Phi) {
-                        nodes.add(usage);
+        if (nodes.size() > 0) {
+            // if this is the first block: add all locals to this block
+            if (nodes.get(0) == graph.start()) {
+                for (Node node : graph.getNodes()) {
+                    if (node instanceof Local) {
+                        nodes.add(node);
                     }
                 }
             }
-        }
 
-        for (Node node : nodes) {
-            if (!omittedClasses.contains(node.getClass())) {
-                stream.printf("     <node id='%d'/>%n", node.id());
+            // add all framestates and phis to their blocks
+            for (Node node : block.getInstructions()) {
+                if (node instanceof Instruction && ((Instruction) node).stateAfter() != null) {
+                    nodes.add(((Instruction) node).stateAfter());
+                }
+                if (node instanceof Merge) {
+                    Merge merge = (Merge) node;
+                    if (merge.stateBefore() != null) {
+                        nodes.add(merge.stateBefore());
+                    }
+                    for (Node usage : merge.usages()) {
+                        if (usage instanceof Phi) {
+                            nodes.add(usage);
+                        }
+                    }
+                }
+            }
+
+            for (Node node : nodes) {
+                if (!omittedClasses.contains(node.getClass())) {
+                    stream.printf("     <node id='%d'/>%n", node.id());
+                }
             }
         }
         stream.printf("    </nodes>%n");
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Wed Jun 08 22:41:16 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Thu Jun 09 11:30:58 2011 +0200
@@ -532,7 +532,7 @@
     @Override
     public void visitMonitorAddress(MonitorAddress x) {
         CiValue result = createResultVariable(x);
-        lir.monitorAddress(x.monitor(), result);
+        lir.monitorAddress(x.monitorIndex(), result);
     }
 
     /**
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Wed Jun 08 22:41:16 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Thu Jun 09 11:30:58 2011 +0200
@@ -70,12 +70,12 @@
     public void build() {
         new GraphBuilderPhase(compilation, compilation.method, false, false).apply(compilation.graph);
         printGraph("After GraphBuilding", compilation.graph);
-        //new DuplicationPhase().apply(compilation.graph);
+        new DuplicationPhase().apply(compilation.graph);
         new DeadCodeEliminationPhase().apply(compilation.graph);
         printGraph("After DeadCodeElimination", compilation.graph);
 
         if (GraalOptions.Inline) {
-            new InliningPhase(compilation, this).apply(compilation.graph);
+            new InliningPhase(compilation, this, GraalOptions.TraceInlining).apply(compilation.graph);
             printGraph("After Ininling", compilation.graph);
         }
 
@@ -173,7 +173,12 @@
         int maxLocks = 0;
         for (Node node : compilation.graph.getNodes()) {
             if (node instanceof FrameState) {
-                int lockCount = ((FrameState) node).locksSize();
+                FrameState current = (FrameState) node;
+                int lockCount = 0;
+                while (current != null) {
+                    lockCount += current.locksSize();
+                    current = current.outerFrameState();
+                }
                 if (lockCount > maxLocks) {
                     maxLocks = lockCount;
                 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Wed Jun 08 22:41:16 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Thu Jun 09 11:30:58 2011 +0200
@@ -211,14 +211,14 @@
     }
 
     /**
-     * Determines if a given instruction is a phi whose {@linkplain Phi#block() join block} is a given block.
+     * Determines if a given instruction is a phi whose {@linkplain Phi#merge() join block} is a given block.
      *
      * @param value the instruction to test
      * @param block the block that may be the join block of {@code value} if {@code value} is a phi
      * @return {@code true} if {@code value} is a phi and its join block is {@code block}
      */
     private boolean isPhiAtBlock(Value value) {
-        return value instanceof Phi && ((Phi) value).block() == this;
+        return value instanceof Phi && ((Phi) value).merge() == this;
     }
 
 
@@ -229,7 +229,7 @@
      * @param index the index of the value in the frame state
      * @param value the frame state value
      * @param block if {@code value} is a phi, then its inputs are formatted if {@code block} is its
-     *            {@linkplain Phi#block() join point}
+     *            {@linkplain Phi#merge() join point}
      * @return the instruction representation as a string
      */
     public String stateString(int index, Value value) {
@@ -238,7 +238,7 @@
         if (value instanceof Phi) {
             Phi phi = (Phi) value;
             // print phi operands
-            if (phi.block() == this) {
+            if (phi.merge() == this) {
                 sb.append(" [");
                 for (int j = 0; j < phi.valueCount(); j++) {
                     sb.append(' ');
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MonitorAddress.java	Wed Jun 08 22:41:16 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MonitorAddress.java	Thu Jun 09 11:30:58 2011 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.max.graal.compiler.ir;
 
+import java.util.*;
+
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
@@ -34,11 +36,11 @@
     private static final int INPUT_COUNT = 0;
     private static final int SUCCESSOR_COUNT = 0;
 
-    private int monitor;
+    private int monitorIndex;
 
-    public MonitorAddress(int monitor, Graph graph) {
+    public MonitorAddress(int monitorIndex, Graph graph) {
         super(CiKind.Word, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        this.monitor = monitor;
+        this.monitorIndex = monitorIndex;
     }
 
     @Override
@@ -46,18 +48,31 @@
         v.visitMonitorAddress(this);
     }
 
-    public int monitor() {
-        return monitor;
+    public int monitorIndex() {
+        return monitorIndex;
+    }
+
+    public void setMonitorIndex(int monitorIndex) {
+        this.monitorIndex = monitorIndex;
     }
 
     @Override
     public void print(LogStream out) {
-        out.print("monitor_address (").print(monitor()).print(")");
+        out.print("monitor_address (").print(monitorIndex()).print(")");
+    }
+
+
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("monitorIndex", monitorIndex);
+        return properties;
     }
 
     @Override
     public Node copy(Graph into) {
-        MonitorAddress x = new MonitorAddress(monitor, into);
+        MonitorAddress x = new MonitorAddress(monitorIndex, into);
         return x;
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java	Wed Jun 08 22:41:16 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java	Thu Jun 09 11:30:58 2011 +0200
@@ -35,7 +35,7 @@
     private static final int DEFAULT_MAX_VALUES = 2;
 
     private static final int INPUT_COUNT = 1;
-    private static final int INPUT_BLOCK = 0;
+    private static final int INPUT_MERGE = 0;
 
     private final int maxValues;
 
@@ -55,31 +55,31 @@
     }
 
     /**
-     * The join block for this phi.
+     * The merge node for this phi.
      */
-    public Merge block() {
-        return (Merge) inputs().get(super.inputCount() + INPUT_BLOCK);
+    public Merge merge() {
+        return (Merge) inputs().get(super.inputCount() + INPUT_MERGE);
     }
 
-    public Value setBlock(Value n) {
-        return (Merge) inputs().set(super.inputCount() + INPUT_BLOCK, n);
+    public Value setMerge(Value n) {
+        return (Merge) inputs().set(super.inputCount() + INPUT_MERGE, n);
     }
 
     /**
      * Create a new Phi for the specified join block and local variable (or operand stack) slot.
      * @param kind the type of the variable
-     * @param block the join point
+     * @param merge the join point
      * @param graph
      */
-    public Phi(CiKind kind, Merge block, Graph graph) {
-        this(kind, block, DEFAULT_MAX_VALUES, graph);
+    public Phi(CiKind kind, Merge merge, Graph graph) {
+        this(kind, merge, DEFAULT_MAX_VALUES, graph);
     }
 
-    public Phi(CiKind kind, Merge block, int maxValues, Graph graph) {
+    public Phi(CiKind kind, Merge merge, int maxValues, Graph graph) {
         super(kind, INPUT_COUNT + maxValues, SUCCESSOR_COUNT, graph);
         this.maxValues = maxValues;
         usedInputCount = 0;
-        setBlock(block);
+        setMerge(merge);
     }
 
     /**
@@ -148,7 +148,7 @@
         assert !this.isDeleted() && !y.isDeleted();
         Phi phi = this;
         if (usedInputCount == maxValues) {
-            phi = new Phi(kind, block(), maxValues * 2, graph());
+            phi = new Phi(kind, merge(), maxValues * 2, graph());
             for (int i = 0; i < valueCount(); ++i) {
                 phi.addInput(valueAt(i));
             }
@@ -166,6 +166,7 @@
         for (int i = index + 1; i < valueCount(); ++i) {
             setValueAt(i - 1, valueAt(i));
         }
+        setValueAt(valueCount() - 1, Node.Null);
         usedInputCount--;
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Wed Jun 08 22:41:16 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Thu Jun 09 11:30:58 2011 +0200
@@ -30,17 +30,15 @@
 
 public class DeadCodeEliminationPhase extends Phase {
 
-    private NodeBitMap alive;
-    private NodeWorklist worklist;
+    private NodeFlood flood;
     private Graph graph;
 
     @Override
     protected void run(Graph graph) {
         this.graph = graph;
-        this.alive = graph.createNodeBitMap();
-        this.worklist = graph.createNodeWorklist();
+        this.flood = graph.createNodeFlood();
 
-        worklist.add(graph.start());
+        flood.add(graph.start());
 
         iterateSuccessors();
         disconnectCFGNodes();
@@ -63,20 +61,20 @@
     }
 
     private void iterateSuccessors() {
-        for (Node current : worklist) {
+        for (Node current : flood) {
             for (Node successor : current.successors()) {
-                worklist.add(successor);
+                flood.add(successor);
             }
         }
     }
 
     private void disconnectCFGNodes() {
         for (Node node : graph.getNodes()) {
-            if (node != Node.Null && !worklist.isMarked(node) && isCFG(node)) {
+            if (node != Node.Null && !flood.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 != Node.Null && flood.isMarked(successor)) {
                         if (successor instanceof Merge) {
                             ((Merge) successor).removePhiPredecessor(node);
                         }
@@ -90,7 +88,7 @@
 
     private void deleteCFGNodes() {
         for (Node node : graph.getNodes()) {
-            if (node != Node.Null && !worklist.isMarked(node) && isCFG(node)) {
+            if (node != Node.Null && !flood.isMarked(node) && isCFG(node)) {
                 node.delete();
             }
         }
@@ -98,22 +96,26 @@
 
     private void iterateInputs() {
         for (Node node : graph.getNodes()) {
-            if (node != Node.Null && worklist.isMarked(node)) {
+            if (node != Node.Null && flood.isMarked(node)) {
                 for (Node input : node.inputs()) {
-                    worklist.add(input);
+                    if (!isCFG(input)) {
+                        flood.add(input);
+                    }
                 }
             }
         }
-        for (Node current : worklist) {
+        for (Node current : flood) {
             for (Node input : current.inputs()) {
-                worklist.add(input);
+                if (!isCFG(input)) {
+                    flood.add(input);
+                }
             }
         }
     }
 
     private void disconnectNonCFGNodes() {
         for (Node node : graph.getNodes()) {
-            if (node != Node.Null && !worklist.isMarked(node) && !isCFG(node)) {
+            if (node != Node.Null && !flood.isMarked(node) && !isCFG(node)) {
                 node.inputs().clearAll();
             }
         }
@@ -121,7 +123,7 @@
 
     private void deleteNonCFGNodes() {
         for (Node node : graph.getNodes()) {
-            if (node != Node.Null && !worklist.isMarked(node) && !isCFG(node)) {
+            if (node != Node.Null && !flood.isMarked(node) && !isCFG(node)) {
                 node.delete();
             }
         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Wed Jun 08 22:41:16 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Thu Jun 09 11:30:58 2011 +0200
@@ -42,10 +42,12 @@
     private final Queue<Invoke> invokes = new ArrayDeque<Invoke>();
     private final Queue<RiMethod> methods = new ArrayDeque<RiMethod>();
     private int inliningSize;
+    private final boolean trace;
 
-    public InliningPhase(GraalCompilation compilation, IR ir) {
+    public InliningPhase(GraalCompilation compilation, IR ir, boolean trace) {
         this.compilation = compilation;
         this.ir = ir;
+        this.trace = trace;
     }
 
     private void addToQueue(Invoke invoke, RiMethod method) {
@@ -54,37 +56,40 @@
         inliningSize += method.code().length;
     }
 
+    static HashMap<RiMethod, Integer> methodCount = new HashMap<RiMethod, Integer>();
     @Override
     protected void run(Graph graph) {
         inliningSize = compilation.method.code().length;
-        int iterations = GraalOptions.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;
+        for (int iterations = 0; iterations < GraalOptions.MaximumInlineLevel; iterations++) {
+            for (Invoke invoke : graph.getNodes(Invoke.class)) {
+                RiMethod target = invoke.target;
+                if (invoke.stateAfter() == null || invoke.stateAfter().locksSize() > 0) {
+                    if (trace) {
+                        System.out.println("lock...");
                     }
-                    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 (GraalOptions.TraceInlining) {
-                                    System.out.println("registering concrete method assumption...");
-                                }
-                                compilation.assumptions.recordConcreteMethod(invoke.target, concrete);
-                                addToQueue(invoke, concrete);
+                    continue;
+                }
+                if (!checkInliningConditions(invoke) || !target.isResolved() || Modifier.isNative(target.accessFlags())) {
+                    continue;
+                }
+                if (target.canBeStaticallyBound()) {
+                    if (checkInliningConditions(invoke.target, iterations)) {
+                        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, iterations)) {
+                            if (trace) {
+                                System.out.println("recording concrete method assumption...");
                             }
+                            compilation.assumptions.recordConcreteMethod(invoke.target, concrete);
+                            addToQueue(invoke, concrete);
                         }
                     }
-                    if (inliningSize > GraalOptions.MaximumInstructionCount) {
-                        break;
-                    }
+                }
+                if (inliningSize > GraalOptions.MaximumInstructionCount) {
+                    break;
                 }
             }
 
@@ -97,56 +102,82 @@
             while ((invoke = invokes.poll()) != null) {
                 RiMethod method = methods.remove();
                 inlineMethod(invoke, method);
+
+                if (methodCount.get(method) == null) {
+                    methodCount.put(method, 1);
+                } else {
+                    methodCount.put(method, methodCount.get(method) + 1);
+                }
             }
             DeadCodeEliminationPhase dce = new DeadCodeEliminationPhase();
             dce.apply(graph);
 
             if (inliningSize > GraalOptions.MaximumInstructionCount) {
-                if (GraalOptions.TraceInlining) {
+                if (trace) {
                     System.out.println("inlining stopped: MaximumInstructionCount reached");
                 }
                 break;
             }
-        } while(--iterations > 0);
+        }
+
+        if (trace) {
+            int inlined = 0;
+            int duplicate = 0;
+            for (Map.Entry<RiMethod, Integer> entry : methodCount.entrySet()) {
+                inlined += entry.getValue();
+                duplicate += entry.getValue() - 1;
+            }
+            if (inlined > 0) {
+                System.out.printf("overhead_: %d (%5.3f %%)\n", duplicate, duplicate * 100.0 / inlined);
+            }
+        }
     }
 
     private boolean checkInliningConditions(Invoke invoke) {
-        String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", invoke.target, false);
+        String name = !trace ? null : invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", invoke.target, false);
         if (invoke.predecessors().size() == 0) {
-            if (GraalOptions.TraceInlining) {
+            if (trace) {
                 System.out.println("not inlining " + name + " because the invoke is dead code");
             }
             return false;
         }
+        if (invoke.stateAfter() == null) {
+            if (trace) {
+                System.out.println("not inlining " + name + " because of missing frame state");
+            }
+        }
         return true;
     }
 
-    private boolean checkInliningConditions(RiMethod method) {
-        String name = null;
-        if (GraalOptions.TraceInlining) {
-            name = CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
-        }
+    private boolean checkInliningConditions(RiMethod method, int iterations) {
+        String name = !trace ? null : CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
         if (method.code().length > GraalOptions.MaximumInlineSize) {
-            if (GraalOptions.TraceInlining) {
+            if (trace) {
                 System.out.println("not inlining " + name + " because of code size");
             }
             return false;
         }
         if (!method.holder().isInitialized()) {
-            if (GraalOptions.TraceInlining) {
+            if (trace) {
                 System.out.println("not inlining " + name + " because of non-initialized class");
             }
             return false;
         }
+        if (method == compilation.method && iterations > GraalOptions.MaximumRecursiveInlineLevel) {
+            if (trace) {
+                System.out.println("not inlining " + name + " because of recursive inlining limit");
+            }
+            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)";
+        String name = !trace ? null : invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
         FrameState stateAfter = invoke.stateAfter();
         Instruction exceptionEdge = invoke.exceptionEdge();
 
-        if (GraalOptions.TraceInlining) {
+        if (trace) {
             System.out.printf("Building graph for %s, locals: %d, stack: %d\n", name, method.maxLocals(), method.maxStackSize());
         }
 
@@ -167,6 +198,8 @@
             parameters[0] = invoke.argument(0);
         }
 
+        invoke.inputs().clearAll();
+
         HashMap<Node, Node> replacements = new HashMap<Node, Node>();
         ArrayList<Node> nodes = new ArrayList<Node>();
         ArrayList<Node> frameStates = new ArrayList<Node>();
@@ -192,7 +225,7 @@
             }
         }
 
-        if (GraalOptions.TraceInlining) {
+        if (trace) {
             ir.printGraph("Subgraph " + CiUtil.format("%H.%n(%p):%r", method, false), graph);
             System.out.println("inlining " + name + ": " + frameStates.size() + " frame states, " + nodes.size() + " nodes");
         }
@@ -209,6 +242,17 @@
 
         Map<Node, Node> duplicates = compilation.graph.addDuplicate(nodes, replacements);
 
+        int monitorIndexDelta = stateAfter.locksSize();
+        if (monitorIndexDelta > 0) {
+            for (Map.Entry<Node, Node> entry : duplicates.entrySet()) {
+                if (entry.getValue() instanceof MonitorAddress) {
+                    System.out.println("Adjusting monitor index");
+                    MonitorAddress address = (MonitorAddress) entry.getValue();
+                    address.setMonitorIndex(address.monitorIndex() + monitorIndexDelta);
+                }
+            }
+        }
+
         if (returnNode != null) {
             List<Node> usages = new ArrayList<Node>(invoke.usages());
             for (Node usage : usages) {
@@ -228,30 +272,17 @@
             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;
 
+                Unwind unwindDuplicate = (Unwind) duplicates.get(unwindNode);
                 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()));
-                    }
+                    usage.inputs().replace(obj, unwindDuplicate.exception());
                 }
-                Node unwindDuplicate = duplicates.get(unwindNode);
                 unwindDuplicate.inputs().clearAll();
 
                 assert unwindDuplicate.predecessors().size() == 1;
@@ -260,9 +291,7 @@
                 unwindPred.successors().setAndClear(index, obj, 0);
 
                 obj.inputs().clearAll();
-                obj.delete();
                 unwindDuplicate.delete();
-
             }
         }
 
@@ -274,7 +303,7 @@
             }
         }
 
-        if (GraalOptions.TraceInlining) {
+        if (trace) {
             ir.printGraph("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false), compilation.graph);
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Schedule.java	Wed Jun 08 22:41:16 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Schedule.java	Thu Jun 09 11:30:58 2011 +0200
@@ -216,9 +216,9 @@
         for (Node usage : n.usages()) {
             if (usage instanceof Phi) {
                 Phi phi = (Phi) usage;
-                Merge merge = phi.block();
+                Merge merge = phi.merge();
                 Block mergeBlock = nodeToBlock.get(merge);
-                assert mergeBlock != null;
+                assert mergeBlock != null : "no block for merge " + merge.id();
                 for (int i = 0; i < phi.valueCount(); ++i) {
                     if (phi.valueAt(i) == n) {
                         if (mergeBlock.getPredecessors().size() == 0) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Wed Jun 08 22:41:16 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Thu Jun 09 11:30:58 2011 +0200
@@ -287,7 +287,7 @@
         if (p != null) {
             if (p instanceof Phi) {
                 Phi phi = (Phi) p;
-                if (phi.block() == block) {
+                if (phi.merge() == block) {
                     return phi;
                 }
             }
@@ -307,7 +307,7 @@
         Value p = localAt(i);
         if (p instanceof Phi) {
             Phi phi = (Phi) p;
-            if (phi.block() == block) {
+            if (phi.merge() == block) {
                 return phi;
             }
         }
@@ -357,11 +357,11 @@
             Value x = valueAt(i);
             if (x != null) {
                 Value y = other.valueAt(i);
-                if (x != y || ((x instanceof Phi) && ((Phi) x).block() == block)) {
+                if (x != y || ((x instanceof Phi) && ((Phi) x).merge() == block)) {
                     if (typeMismatch(x, y)) {
                         if (x instanceof Phi) {
                             Phi phi = (Phi) x;
-                            if (phi.block() == block) {
+                            if (phi.merge() == block) {
                                 phi.makeDead();
                             }
                         }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java	Wed Jun 08 22:41:16 2011 +0200
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java	Thu Jun 09 11:30:58 2011 +0200
@@ -26,6 +26,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -62,6 +63,53 @@
         return Collections.unmodifiableList(nodes);
     }
 
+    public static class TypedNodeIterator<T> implements Iterator<T> {
+        private final Class<T> type;
+        private final Iterator<Node> iter;
+        private Node nextNode;
+
+        public TypedNodeIterator(Class<T> type, Iterator<Node> iter) {
+            this.type = type;
+            this.iter = iter;
+            forward();
+        }
+
+        private void forward() {
+            do {
+                if (!iter.hasNext()) {
+                    nextNode = null;
+                    return;
+                }
+                nextNode = iter.next();
+            } while (nextNode == null || !type.isInstance(nextNode));
+        }
+
+        public boolean hasNext() {
+            return nextNode != null;
+        }
+
+        @SuppressWarnings("unchecked")
+        public T next() {
+            try {
+                return (T) nextNode;
+            } finally {
+                forward();
+            }
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    public <T extends Node> Iterable<T> getNodes(final Class<T> type) {
+        return new Iterable<T>() {
+            public Iterator<T> iterator() {
+                return new TypedNodeIterator<T>(type, nodes.iterator());
+            }
+        };
+    }
+
     int register(Node node) {
         int id = nextId++;
         nodes.add(id, node);
@@ -85,8 +133,8 @@
         return new NodeMap<T>(this);
     }
 
-    public NodeWorklist createNodeWorklist() {
-        return new NodeWorklist(this);
+    public NodeFlood createNodeFlood() {
+        return new NodeFlood(this);
     }
 
     public Map<Node, Node> addDuplicate(Collection<Node> nodes, Map<Node, Node> replacements) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeFlood.java	Thu Jun 09 11:30:58 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.max.graal.graph;
+
+import java.util.ArrayDeque;
+import java.util.Iterator;
+import java.util.Queue;
+
+
+public class NodeFlood implements Iterable<Node> {
+    private final NodeBitMap visited;
+    private final Queue<Node> worklist;
+
+    NodeFlood(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/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeWorklist.java	Wed Jun 08 22:41:16 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/*
- * 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.max.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/runscimark.sh	Wed Jun 08 22:41:16 2011 +0200
+++ b/runscimark.sh	Thu Jun 09 11:30:58 2011 +0200
@@ -23,5 +23,5 @@
 for (( i = 1; i <= ${COUNT}; i++ ))      ### Outer for loop ###
 do
   echo "$i "
-  ${JDK7}/jre/bin/java -client -d64 -graal -esa -ea -Xms32m -Xmx100m -Xbootclasspath/a:${SCIMARK} -C1X:+PrintTimers $@ jnt.scimark2.commandline
+  ${JDK7}/jre/bin/java -client -d64 -graal -esa -ea -Xms32m -Xmx100m -Xbootclasspath/a:${SCIMARK} -G:+Time $@ jnt.scimark2.commandline
 done
--- a/runtests.sh	Wed Jun 08 22:41:16 2011 +0200
+++ b/runtests.sh	Thu Jun 09 11:30:58 2011 +0200
@@ -12,4 +12,4 @@
   exit 1;
 fi
 TESTDIR=${MAXINE}/com.oracle.max.vm/test
-${JDK7}/bin/java -client -d64 -graal -ea -esa -Xcomp $* -XX:+PrintCompilation -XX:CompileOnly=jtt -Xbootclasspath/p:"${MAXINE}/com.oracle.max.vm/bin" -Xbootclasspath/p:"${MAXINE}/com.oracle.max.base/bin" $1 test.com.sun.max.vm.compiler.JavaTester -verbose=1 -gen-run-scheme=false -run-scheme-package=all ${TESTDIR}/jtt/bytecode ${TESTDIR}/jtt/except ${TESTDIR}/jtt/hotpath ${TESTDIR}/jtt/jdk ${TESTDIR}/jtt/lang ${TESTDIR}/jtt/loop ${TESTDIR}/jtt/micro ${TESTDIR}/jtt/optimize ${TESTDIR}/jtt/reflect ${TESTDIR}/jtt/threads
+${JDK7}/bin/java -client -d64 -graal -ea -esa -Xcomp -XX:+PrintCompilation -XX:CompileOnly=jtt -Xbootclasspath/p:"${MAXINE}/com.oracle.max.vm/bin" -Xbootclasspath/p:"${MAXINE}/com.oracle.max.base/bin" $@ test.com.sun.max.vm.compiler.JavaTester -verbose=1 -gen-run-scheme=false -run-scheme-package=all ${TESTDIR}/jtt/bytecode ${TESTDIR}/jtt/except ${TESTDIR}/jtt/hotpath ${TESTDIR}/jtt/jdk ${TESTDIR}/jtt/lang ${TESTDIR}/jtt/loop ${TESTDIR}/jtt/micro ${TESTDIR}/jtt/optimize ${TESTDIR}/jtt/reflect ${TESTDIR}/jtt/threads