changeset 2948:c76db61fbb73

Merge.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Fri, 10 Jun 2011 21:52:19 +0200
parents e86e83c5adbc (current diff) 668603cb3263 (diff)
children 4db4e8cb6bd6
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.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/GraphBuilderPhase.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/NodeBitMap.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMExitsNative.java graal/hotspot/hotspot Default.launch
diffstat 33 files changed, 610 insertions(+), 148 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Fri Jun 10 21:52:19 2011 +0200
@@ -55,6 +55,7 @@
     public static boolean ZapStackOnMethodEntry              = ____;
     public static boolean StressLinearScan                   = ____;
     public static boolean BailoutOnException                 = ____;
+    public static boolean DeoptALot                          = ____;
 
     /**
      * See {@link Filter#Filter(String, Object)}.
@@ -104,8 +105,9 @@
     // Code generator settings
     public static boolean GenLIR                             = true;
     public static boolean GenCode                            = true;
+    public static boolean UseBranchPrediction                = ____;
 
-    public static boolean UseConstDirectCall                 = false;
+    public static boolean UseConstDirectCall                 = ____;
 
     public static boolean GenSpecialDivChecks                = ____;
     public static boolean GenAssertionCode                   = ____;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java	Fri Jun 10 21:52:19 2011 +0200
@@ -164,7 +164,12 @@
                 assert lastOp instanceof LIRBranch : "branch must be of type LIRBranch";
                 LIRBranch lastBranch = (LIRBranch) lastOp;
 
-                assert lastBranch.block() != null : "last branch must always have a block as target";
+                if (lastBranch.block() == null) {
+                    // this might target a deoptimization stub...
+                    // TODO check if the target is really a deopt stub...
+//                    assert lastBranch.block() != null : "last branch must always have a block as target, current block #" + block.blockID();
+                    continue;
+                }
                 assert lastBranch.label() == lastBranch.block().label() : "must be equal";
 
                 if (lastBranch.info == null) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Fri Jun 10 21:52:19 2011 +0200
@@ -2122,7 +2122,7 @@
         }
 
         if (compilation.compiler.isObserved()) {
-            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, label, compilation.graph, hirValid, true));
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, label, /*compilation.graph*/ null, hirValid, true));
         }
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Fri Jun 10 21:52:19 2011 +0200
@@ -140,6 +140,7 @@
         stream.println("  </controlFlow>");
 
         stream.println(" </graph>");
+        flush();
     }
 
     private List<Edge> printNodes(Collection<Node> nodes, boolean shortNames, NodeMap<Block> nodeToBlock) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java	Fri Jun 10 21:52:19 2011 +0200
@@ -140,7 +140,7 @@
 
     @Override
     public void compilationEvent(CompilationEvent event) {
-        if (printer != null && event.getGraph() != null) {
+        if (printer != null && event.getGraph() != null && event.isHIRValid()) {
             Graph graph = event.getGraph();
             printer.print(graph, event.getLabel(), true);
         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Fri Jun 10 21:52:19 2011 +0200
@@ -38,6 +38,7 @@
 import com.oracle.max.graal.compiler.globalstub.*;
 import com.oracle.max.graal.compiler.graph.*;
 import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.compiler.value.*;
@@ -207,8 +208,10 @@
     public static class DeoptimizationStub {
         public final Label label = new Label();
         public final LIRDebugInfo info;
+        public final DeoptAction action;
 
-        public DeoptimizationStub(FrameState state) {
+        public DeoptimizationStub(DeoptAction action, FrameState state) {
+            this.action = action;
             info = new LIRDebugInfo(state);
         }
     }
@@ -293,12 +296,22 @@
         if (Modifier.isSynchronized(compilation.method.accessFlags())) {
             bci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
         }
+
+        boolean withReceiver = !Modifier.isStatic(compilation.method.accessFlags());
+        CiKind[] arguments = Util.signatureToKinds(compilation.method.signature(), withReceiver ? CiKind.Object : null);
+        int[] argumentSlots = new int[arguments.length];
+        int slot = 0;
+        for (int arg = 0; arg < arguments.length; arg++) {
+            argumentSlots[arg] = slot;
+            slot += arguments[arg].sizeInSlots();
+        }
+
         FrameState fs = new FrameState(compilation.method, bci, compilation.method.maxLocals(), 0, 0, compilation.graph);
         for (Node node : compilation.graph.start().usages()) {
             if (node instanceof Local) {
                 Local local = (Local) node;
                 int i = local.index();
-                fs.storeLocal(i, local);
+                fs.storeLocal(argumentSlots[i], local);
 
                 CiValue src = args.locations[i];
                 assert src.isLegal() : "check";
@@ -310,9 +323,21 @@
                 setResult(local, dest);
             }
         }
+        assert checkOperands(fs);
         return fs;
     }
 
+    private boolean checkOperands(FrameState fs) {
+        boolean withReceiver = !Modifier.isStatic(compilation.method.accessFlags());
+        CiKind[] arguments = Util.signatureToKinds(compilation.method.signature(), withReceiver ? CiKind.Object : null);
+        int slot = 0;
+        for (CiKind kind : arguments) {
+            assert fs.localAt(slot) != null : "slot: " + slot;
+            slot += kind.sizeInSlots();
+        }
+        return true;
+    }
+
     @Override
     public void visitCheckCast(CheckCast x) {
         XirArgument obj = toXirArgument(x.object());
@@ -395,7 +420,7 @@
             deoptimizationStubs = new ArrayList<DeoptimizationStub>();
         }
 
-        DeoptimizationStub stub = new DeoptimizationStub(state);
+        DeoptimizationStub stub = new DeoptimizationStub(DeoptAction.InvalidateReprofile, state);
         deoptimizationStubs.add(stub);
 
         emitCompare(x.node());
@@ -954,7 +979,8 @@
 
     @Override
     public void visitDeoptimize(Deoptimize deoptimize) {
-        DeoptimizationStub stub = new DeoptimizationStub(lastState);
+        assert lastState != null : "deoptimize always needs a state";
+        DeoptimizationStub stub = new DeoptimizationStub(deoptimize.action(), lastState);
         addDeoptimizationStub(stub);
         lir.branch(Condition.TRUE, stub.label, stub.info);
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java	Fri Jun 10 21:52:19 2011 +0200
@@ -26,6 +26,7 @@
 
 import java.util.*;
 
+import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.ir.*;
 import com.sun.cri.bytecode.*;
@@ -136,6 +137,11 @@
     public static class DeoptBlock  extends Block {
     }
 
+    public static class BranchOverride {
+        public DeoptBlock block;
+        public boolean taken;
+    }
+
     private static final Block[] NO_SUCCESSORS = new Block[0];
 
     /**
@@ -151,6 +157,8 @@
 
     private final RiMethod method;
 
+    public final HashMap<Integer, BranchOverride> branchOverride;
+
     private Block[] blockMap;
 
     private BitSet canTrap;
@@ -167,6 +175,7 @@
         }
         this.blocks = new ArrayList<Block>();
         this.storesInLoops = new BitSet(method.maxLocals());
+        branchOverride = new HashMap<Integer, BranchOverride>();
     }
 
     /**
@@ -260,15 +269,12 @@
                 case IF_ACMPNE: // fall through
                 case IFNULL:    // fall through
                 case IFNONNULL: {
-                    int probability = method.branchProbability(bci);
-//                    if (probability == 0 || probability == 100) {
-//                        System.out.println("prob: " + probability);
-//                    }
                     current = null;
-                    Block b1 = makeBlock(bci + 3);
-                    Block b2 = makeBlock(bci + Bytes.beS2(code, bci + 1));
-//                    Block b1 = probability == 100 ? makeDeoptBlock(bci + 3) : makeBlock(bci + 3);
-//                    Block b2 = probability == 0 ? makeDeoptBlock(bci + Bytes.beS2(code, bci + 1)) : makeBlock(bci + Bytes.beS2(code, bci + 1));
+
+                    int probability = GraalOptions.UseBranchPrediction ? method.branchProbability(bci) : -1;
+
+                    Block b1 = probability == 100 ? makeBranchOverrideBlock(bci, bci + 3, false) : makeBlock(bci + 3);
+                    Block b2 = probability == 0 ? makeBranchOverrideBlock(bci, bci + Bytes.beS2(code, bci + 1), true) : makeBlock(bci + Bytes.beS2(code, bci + 1));
                     setSuccessors(bci, b1, b2);
 
                     assert lengthOf(code, bci) == 3;
@@ -385,11 +391,14 @@
         }
     }
 
-    private Block makeDeoptBlock(int startBci) {
-        System.out.println("Deopt block created");
+    private Block makeBranchOverrideBlock(int branchBci, int startBci, boolean taken) {
         DeoptBlock newBlock = new DeoptBlock();
         newBlock.startBci = startBci;
-        blockMap[startBci] = newBlock;
+        BranchOverride override = new BranchOverride();
+        override.block = newBlock;
+        override.taken = taken;
+        assert branchOverride.get(branchBci) == null;
+        branchOverride.put(branchBci, override);
         return newBlock;
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Fri Jun 10 21:52:19 2011 +0200
@@ -70,7 +70,7 @@
     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);
 
@@ -87,8 +87,8 @@
 
         if (GraalOptions.OptCanonicalizer) {
             new CanonicalizerPhase().apply(graph);
+            new DeadCodeEliminationPhase().apply(compilation.graph);
             printGraph("After Canonicalization", graph);
-            new DeadCodeEliminationPhase().apply(compilation.graph);
         }
 
         new LoweringPhase().apply(graph);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java	Fri Jun 10 21:52:19 2011 +0200
@@ -31,10 +31,20 @@
     private static final int INPUT_COUNT = 0;
     private static final int SUCCESSOR_COUNT = 0;
 
-    private String message;
+    public static enum DeoptAction {
+        None,                           // just interpret, do not invalidate nmethod
+        Recompile,                      // recompile the nmethod; need not invalidate
+        InvalidateReprofile,            // invalidate the nmethod, reset IC, maybe recompile
+        InvalidateRecompile,            // invalidate the nmethod, recompile (probably)
+        InvalidateStopCompiling,        // invalidate the nmethod and do not compile
+    }
 
-    public Deoptimize(Graph graph) {
+    private String message;
+    private final DeoptAction action;
+
+    public Deoptimize(DeoptAction action, Graph graph) {
         super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.action = action;
     }
 
     public void setMessage(String message) {
@@ -45,6 +55,10 @@
         return message;
     }
 
+    public DeoptAction action() {
+        return action;
+    }
+
     @Override
     public void accept(ValueVisitor v) {
         v.visitDeoptimize(this);
@@ -62,7 +76,7 @@
 
     @Override
     public Node copy(Graph into) {
-        Deoptimize x = new Deoptimize(into);
+        Deoptimize x = new Deoptimize(action, into);
         x.setMessage(message);
         return x;
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Local.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Local.java	Fri Jun 10 21:52:19 2011 +0200
@@ -22,8 +22,11 @@
  */
 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.bytecode.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
 
@@ -34,15 +37,38 @@
 public final class Local extends FloatingNode {
 
     private static final int INPUT_COUNT = 1;
+    private static final int INPUT_START = 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 start node of the graph that this local belongs to. This is used for correctly scheduling the locals.
+     */
+     private StartNode start() {
+        return (StartNode) inputs().get(super.inputCount() + INPUT_START);
+    }
+
+     private void setStart(StartNode n) {
+         inputs().set(super.inputCount() + INPUT_START, n);
+     }
+
     private final int index;
     private RiType declaredType;
 
-    public Local(CiKind kind, int javaIndex, Graph graph) {
+    public Local(CiKind kind, int javaIndex, StartNode start, Graph graph) {
         super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.index = javaIndex;
+        setStart(start);
     }
 
     /**
@@ -81,18 +107,15 @@
     }
 
     @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
-
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("index", index());
+        return properties;
     }
 
     @Override
     public Node copy(Graph into) {
-        Local x = new Local(kind, index, into);
+        Local x = new Local(kind, index, start(), into);
         x.setDeclaredType(declaredType());
         return x;
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Negate.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Negate.java	Fri Jun 10 21:52:19 2011 +0200
@@ -23,6 +23,7 @@
 package com.oracle.max.graal.compiler.ir;
 
 import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.bytecode.*;
@@ -32,6 +33,7 @@
  * The {@code NegateOp} instruction negates its operand.
  */
 public final class Negate extends FloatingNode {
+    private static final NegateCanonicalizerOp CANONICALIZER = new NegateCanonicalizerOp();
 
     private static final int INPUT_COUNT = 2;
     private static final int INPUT_X = 0;
@@ -103,4 +105,31 @@
         Negate x = new Negate(kind, 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 NegateCanonicalizerOp implements CanonicalizerOp {
+        @Override
+        public Node canonical(Node node) {
+            Negate negate = (Negate) node;
+            Value x = negate.x();
+            Graph graph = negate.graph();
+            if (x.isConstant()) {
+                switch (x.kind) {
+                    case Int: return Constant.forInt(-x.asConstant().asInt(), graph);
+                    case Long: return Constant.forLong(-x.asConstant().asLong(), graph);
+                    case Float: return Constant.forFloat(-x.asConstant().asFloat(), graph);
+                    case Double: return Constant.forDouble(-x.asConstant().asDouble(), graph);
+                }
+            }
+            return negate;
+        }
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Fri Jun 10 21:52:19 2011 +0200
@@ -205,6 +205,4 @@
         properties.put("operand", operand == null ? "null" : operand.toString());
         return properties;
     }
-
-
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Fri Jun 10 21:52:19 2011 +0200
@@ -22,46 +22,30 @@
  */
 package com.oracle.max.graal.compiler.phases;
 
-import java.util.*;
-
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.graph.*;
 
+/* TODO (gd) Canonicalize :
+ * - Compare & If
+ * - InstanceOf (if it's not transformed into a Condition for Compare)
+ * - Switches
+ */
 public class CanonicalizerPhase extends Phase {
-
+    private static final int MAX_ITERATION_PER_NODE = 10;
 
     @Override
     protected void run(Graph graph) {
-        NodeBitMap visited = graph.createNodeBitMap();
-        List<Node> nodes = new ArrayList<Node>(graph.getNodes());
-        for (Node n : nodes) {
-            if (n == null) {
-                continue;
-            }
-            if (!n.isDeleted() && !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);
-                //System.out.println("-->" + n + " canonicalized to " + canonical);
-                GraalMetrics.NodesCanonicalized++;
+        NodeWorkList nodeWorkList = graph.createNodeWorkList(true, MAX_ITERATION_PER_NODE);
+        for (Node node : nodeWorkList) {
+            CanonicalizerOp op = node.lookup(CanonicalizerOp.class);
+            if (op != null) {
+                Node canonical = op.canonical(node);
+                if (canonical != node) {
+                    node.replace(canonical);
+                    nodeWorkList.replaced(canonical, node, EdgeType.USAGES);
+                    //System.out.println("-->" + n + " canonicalized to " + canonical);
+                    GraalMetrics.NodesCanonicalized++;
+                }
             }
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Fri Jun 10 21:52:19 2011 +0200
@@ -38,6 +38,27 @@
         this.graph = graph;
         this.flood = graph.createNodeFlood();
 
+        // remove chained Merges
+//        for (Merge merge : graph.getNodes(Merge.class)) {
+//            if (merge.predecessors().size() == 1 && merge.usages().size() == 0) {
+//                if (merge.successors().get(0) instanceof Merge) {
+//                    Node pred = merge.predecessors().get(0);
+//                    int predIndex = merge.predecessorsIndex().get(0);
+//                    pred.successors().setAndClear(predIndex, merge, 0);
+//                    merge.delete();
+//                }
+//            }
+//        }
+//        Node startSuccessor = graph.start().successors().get(0);
+//        if (startSuccessor instanceof Merge) {
+//            Merge startMerge = (Merge) startSuccessor;
+//            if (startMerge.predecessors().size() == 1 && startMerge.usages().size() == 0) {
+//                int predIndex = startMerge.predecessorsIndex().get(0);
+//                graph.start().successors().setAndClear(predIndex, startMerge, 0);
+//                startMerge.delete();
+//            }
+//        }
+
         flood.add(graph.start());
 
         iterateSuccessors();
@@ -96,6 +117,9 @@
 
     private void iterateInputs() {
         for (Node node : graph.getNodes()) {
+            if (node instanceof Local) {
+                flood.add(node);
+            }
             if (node != Node.Null && flood.isMarked(node)) {
                 for (Node input : node.inputs()) {
                     if (!isCFG(input)) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Fri Jun 10 21:52:19 2011 +0200
@@ -31,10 +31,10 @@
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.graph.*;
-import com.oracle.max.graal.compiler.graph.BlockMap.DeoptBlock;
 import com.oracle.max.graal.compiler.graph.BlockMap.*;
 import com.oracle.max.graal.compiler.graph.BlockMap.Block;
 import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.compiler.value.*;
@@ -78,11 +78,12 @@
     // bci-to-block mapping
     private Block[] blockFromBci;
     private ArrayList<Block> blockList;
+    private HashMap<Integer, BranchOverride> branchOverride;
 
     private int nextBlockNumber;
 
     private Value methodSynchronizedObject;
-    private CiExceptionHandler syncHandler;
+    private CiExceptionHandler unwindHandler;
 
     private Block unwindBlock;
     private Block returnBlock;
@@ -145,6 +146,7 @@
 
         // 2. compute the block map, setup exception handlers and get the entrypoint(s)
         BlockMap blockMap = compilation.getBlockMap(method);
+        this.branchOverride = blockMap.branchOverride;
 
         blockList = new ArrayList<Block>(blockMap.blocks);
         blockFromBci = new Block[method.code().length];
@@ -152,7 +154,7 @@
             int blockID = nextBlockNumber();
             assert blockID == i;
             Block block = blockList.get(i);
-            if (block.startBci >= 0) {
+            if (block.startBci >= 0 && !(block instanceof BlockMap.DeoptBlock)) {
                 blockFromBci[block.startBci] = block;
             }
         }
@@ -171,13 +173,13 @@
             finishStartBlock(startBlock);
 
             // 4A.3 setup an exception handler to unlock the root method synchronized object
-            syncHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null);
+            unwindHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null);
         } 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);
+                unwindHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null);
             }
         }
 
@@ -380,7 +382,7 @@
         }
 
         if (firstHandler == null) {
-            firstHandler = syncHandler;
+            firstHandler = unwindHandler;
         }
 
         if (firstHandler != null) {
@@ -435,7 +437,7 @@
             // this is a load of class constant which might be unresolved
             RiType riType = (RiType) con;
             if (!riType.isResolved()) {
-                append(new Deoptimize(graph));
+                append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
                 frameState.push(CiKind.Object, append(Constant.forObject(null, graph)));
             } else {
                 frameState.push(CiKind.Object, append(new Constant(riType.getEncoding(Representation.JavaClass), graph)));
@@ -654,9 +656,20 @@
         assert !x.isDeleted() && !y.isDeleted();
         If ifNode = new If(new Compare(x, cond, y, graph), graph);
         append(ifNode);
-        Instruction tsucc = createTargetAt(stream().readBranchDest(), frameState);
+        BlockMap.BranchOverride override = branchOverride.get(bci());
+        Instruction tsucc;
+        if (override == null || override.taken == false) {
+            tsucc = createTargetAt(stream().readBranchDest(), frameState);
+        } else {
+            tsucc = createTarget(override.block, frameState);
+        }
         ifNode.setBlockSuccessor(0, tsucc);
-        Instruction fsucc = createTargetAt(stream().nextBCI(), frameState);
+        Instruction fsucc;
+        if (override == null || override.taken == true) {
+            fsucc = createTargetAt(stream().nextBCI(), frameState);
+        } else {
+            fsucc = createTarget(override.block, frameState);
+        }
         ifNode.setBlockSuccessor(1, fsucc);
     }
 
@@ -727,7 +740,7 @@
             NewInstance n = new NewInstance(type, cpi, constantPool, graph);
             frameState.apush(append(n));
         } else {
-            append(new Deoptimize(graph));
+            append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
         }
     }
@@ -746,7 +759,7 @@
             NewArray n = new NewObjectArray(type, length, graph);
             frameState.apush(append(n));
         } else {
-            append(new Deoptimize(graph));
+            append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
         }
 
@@ -763,7 +776,7 @@
             NewArray n = new NewMultiArray(type, dims, cpi, constantPool, graph);
             frameState.apush(append(n));
         } else {
-            append(new Deoptimize(graph));
+            append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
         }
     }
@@ -775,7 +788,7 @@
             LoadField load = new LoadField(receiver, field, graph);
             appendOptimizedLoadField(kind, load);
         } else {
-            append(new Deoptimize(graph));
+            append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
             frameState.push(kind.stackKind(), append(Constant.defaultForKind(kind, graph)));
         }
     }
@@ -787,7 +800,7 @@
             StoreField store = new StoreField(receiver, field, value, graph);
             appendOptimizedStoreField(store);
         } else {
-            append(new Deoptimize(graph));
+            append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
         }
     }
 
@@ -807,7 +820,7 @@
                 LoadField load = new LoadField(container, field, graph);
                 appendOptimizedLoadField(kind, load);
             } else {
-                append(new Deoptimize(graph));
+                append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
                 frameState.push(kind.stackKind(), append(Constant.defaultForKind(kind, graph)));
             }
         }
@@ -821,7 +834,7 @@
             StoreField store = new StoreField(container, field, value, graph);
             appendOptimizedStoreField(store);
         } else {
-            append(new Deoptimize(graph));
+            append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
         }
     }
 
@@ -829,7 +842,7 @@
         if (initialized) {
             return appendConstant(holder.getEncoding(representation));
         } else {
-            append(new Deoptimize(graph));
+            append(new Deoptimize(DeoptAction.InvalidateRecompile, graph));
             return null;
         }
     }
@@ -909,10 +922,15 @@
 
     private void appendInvoke(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) {
         CiKind resultType = returnKind(target);
-        Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), method.typeProfile(bci()), graph);
-        Value result = appendWithBCI(invoke);
-        invoke.setExceptionEdge(handleException(null, bci()));
-        frameState.pushReturn(resultType, result);
+        if (GraalOptions.DeoptALot) {
+            append(new Deoptimize(DeoptAction.None, graph));
+            frameState.pushReturn(resultType, Constant.defaultForKind(resultType, graph));
+        } else {
+            Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), method.typeProfile(bci()), graph);
+            Value result = appendWithBCI(invoke);
+            invoke.setExceptionEdge(handleException(null, bci()));
+            frameState.pushReturn(resultType, result);
+        }
     }
 
     private RiType getExactType(RiType staticType, Value receiver) {
@@ -1096,7 +1114,8 @@
 
     private Instruction createTarget(Block block, FrameStateAccess stateAfter) {
         assert block != null && stateAfter != null;
-        assert block.isLoopHeader || block.firstInstruction == null || block.firstInstruction.next() == null : "non-loop block must be iterated after all its predecessors";
+        assert block.isLoopHeader || block.firstInstruction == null || block.firstInstruction.next() == null :
+            "non-loop block must be iterated after all its predecessors. startBci=" + block.startBci + ", " + block.getClass().getSimpleName() + ", " + block.firstInstruction.next();
 
         if (block.isExceptionEntry) {
             assert stateAfter.stackSize() == 1;
@@ -1188,7 +1207,10 @@
     }
 
     private void createDeoptBlock(DeoptBlock block) {
-        append(new Deoptimize(graph));
+//        Merge x = new Merge(graph);
+//        x.setStateBefore(((StateSplit) block.firstInstruction).stateBefore());
+//        append(x);
+        append(new Deoptimize(DeoptAction.InvalidateReprofile, graph));
     }
 
     private void createUnwindBlock(Block block) {
@@ -1225,7 +1247,7 @@
                 Instruction nextDispatch = createTarget(nextBlock, frameState);
                 append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), graph));
             } else {
-                Deoptimize deopt = new Deoptimize(graph);
+                Deoptimize deopt = new Deoptimize(DeoptAction.InvalidateRecompile, graph);
                 deopt.setMessage("unresolved " + block.handler.catchType().name());
                 append(deopt);
                 Instruction nextDispatch = createTarget(nextBlock, frameState);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Fri Jun 10 21:52:19 2011 +0200
@@ -273,11 +273,17 @@
             Node returnDuplicate = duplicates.get(returnNode);
             returnDuplicate.inputs().clearAll();
 
+            Merge mergeAfter = new Merge(compilation.graph);
+
             assert returnDuplicate.predecessors().size() == 1;
             Node returnPred = returnDuplicate.predecessors().get(0);
             int index = returnDuplicate.predecessorsIndex().get(0);
-            returnPred.successors().setAndClear(index, invoke, 0);
+            mergeAfter.successors().setAndClear(0, invoke, 0);
+            returnPred.successors().set(index, mergeAfter);
+
             returnDuplicate.delete();
+
+            mergeAfter.setStateBefore(stateAfter);
         }
 
         if (exceptionEdge != null) {
@@ -306,8 +312,11 @@
         // 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);
+            for (Node node : frameStates) {
+                FrameState frameState = (FrameState) duplicates.get(node);
+                if (!frameState.isDeleted()) {
+                    frameState.setOuterFrameState(outerFrameState);
+                }
             }
         }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Fri Jun 10 21:52:19 2011 +0200
@@ -2070,6 +2070,27 @@
     @Override
     public void emitDeoptizationStub(DeoptimizationStub stub) {
         masm.bind(stub.label);
+        int code;
+        switch(stub.action) {
+            case None:
+                code = 0;
+                break;
+            case Recompile:
+                code = 1;
+                break;
+            case InvalidateReprofile:
+                code = 2;
+                break;
+            case InvalidateRecompile:
+                code = 3;
+                break;
+            case InvalidateStopCompiling:
+                code = 4;
+                break;
+            default:
+                throw Util.shouldNotReachHere();
+        }
+        masm.movq(rscratch1, code);
         directCall(CiRuntimeCall.Deoptimize, stub.info);
         shouldNotReachHere();
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Fri Jun 10 21:52:19 2011 +0200
@@ -509,6 +509,29 @@
     }
 
     @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("bci", bci);
+        properties.put("method", CiUtil.format("%H.%n(%p):%r", method, false));
+        StringBuilder str = new StringBuilder();
+        for (int i = 0; i < localsSize(); i++) {
+            str.append(i == 0 ? "" : ", ").append(localAt(i) == null ? "_" : localAt(i).id());
+        }
+        properties.put("locals", str.toString());
+        str = new StringBuilder();
+        for (int i = 0; i < stackSize(); i++) {
+            str.append(i == 0 ? "" : ", ").append(stackAt(i) == null ? "_" : stackAt(i).id());
+        }
+        properties.put("stack", str.toString());
+        str = new StringBuilder();
+        for (int i = 0; i < locksSize(); i++) {
+            str.append(i == 0 ? "" : ", ").append(lockAt(i) == null ? "_" : lockAt(i).id());
+        }
+        properties.put("locks", str.toString());
+        return properties;
+    }
+
+    @Override
     public Node copy(Graph into) {
         FrameState x = new FrameState(method, bci, localsSize, stackSize, locksSize, into);
         return x;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java	Fri Jun 10 21:52:19 2011 +0200
@@ -58,8 +58,7 @@
         int index = 0;
         if (!isStatic(method.accessFlags())) {
             // add the receiver and assume it is non null
-            Local local = new Local(method.holder().kind(), javaIndex, graph);
-            local.inputs().set(0, graph.start());
+            Local local = new Local(method.holder().kind(), javaIndex, graph.start(), graph);
             local.setDeclaredType(method.holder());
             storeLocal(javaIndex, local);
             javaIndex = 1;
@@ -71,8 +70,7 @@
         for (int i = 0; i < max; i++) {
             RiType type = sig.argumentTypeAt(i, accessingClass);
             CiKind kind = type.kind().stackKind();
-            Local local = new Local(kind, index, graph);
-            local.inputs().set(0, graph.start());
+            Local local = new Local(kind, index, graph.start(), graph);
             if (type.isResolved()) {
                 local.setDeclaredType(type);
             }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java	Fri Jun 10 21:52:19 2011 +0200
@@ -84,10 +84,12 @@
             } while (nextNode == null || !type.isInstance(nextNode));
         }
 
+        @Override
         public boolean hasNext() {
             return nextNode != null;
         }
 
+        @Override
         @SuppressWarnings("unchecked")
         public T next() {
             try {
@@ -97,6 +99,7 @@
             }
         }
 
+        @Override
         public void remove() {
             throw new UnsupportedOperationException();
         }
@@ -104,6 +107,7 @@
 
     public <T extends Node> Iterable<T> getNodes(final Class<T> type) {
         return new Iterable<T>() {
+            @Override
             public Iterator<T> iterator() {
                 return new TypedNodeIterator<T>(type, nodes.iterator());
             }
@@ -137,12 +141,21 @@
         return new NodeFlood(this);
     }
 
+    public NodeWorkList createNodeWorkList() {
+        return new NodeWorkList(this);
+    }
+
+    public NodeWorkList createNodeWorkList(boolean fill, int iterationLimitPerNode) {
+        return new NodeWorkList(this, fill, iterationLimitPerNode);
+    }
+
     public Map<Node, Node> addDuplicate(Collection<Node> nodes, Map<Node, Node> replacements) {
         Map<Node, Node> newNodes = new HashMap<Node, Node>();
         // create node duplicates
         for (Node node : nodes) {
             if (node != null && !replacements.containsKey(node)) {
                 assert node.graph != this;
+                assert !node.isDeleted() : "trying to duplicate deleted node";
                 Node newNode = node.copy(this);
                 assert newNode.getClass() == node.getClass();
                 newNodes.put(node, newNode);
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java	Fri Jun 10 21:52:19 2011 +0200
@@ -130,7 +130,7 @@
 
     public void delete() {
         assert !isDeleted();
-        assert usages.size() == 0 && predecessors.size() == 0 : "id: " + id + ", usages: " + usages.size() + ", predecessors: " + predecessors().size();
+        assert checkDeletion();
         assert predecessorsIndex.size() == 0;
         for (int i = 0; i < inputs.size(); ++i) {
             inputs.set(i, Null);
@@ -145,6 +145,23 @@
         assert isDeleted();
     }
 
+    private boolean checkDeletion() {
+        if (usages.size() != 0 || predecessors.size() != 0) {
+            System.out.println(this.shortName() + ", id: " + id + ", usages: " + usages.size() + ", predecessors: " + predecessors().size());
+            System.out.println("usages:");
+            for (Node n : usages()) {
+                System.out.print(n.id() + " (" + n.shortName() + ") ");
+            }
+            System.out.println("\npreds:");
+            for (Node n : predecessors()) {
+                System.out.print(n.id() + " (" + n.shortName() + ") ");
+            }
+            System.out.println();
+            return false;
+        }
+        return true;
+    }
+
     public Node copy() {
         return copy(graph);
     }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeArray.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeArray.java	Fri Jun 10 21:52:19 2011 +0200
@@ -53,6 +53,7 @@
 
     @Override
     public Node set(int index, Node node) {
+        assert !self().isDeleted() : "trying to set input/successor of deleted node: " + self().shortName();
         assert node == Node.Null || node.graph == self().graph : "node is from different graph: (this=" + self() + ") and (node=" + node + ")";
         assert node == Node.Null || node.id() != Node.DeletedID : "inserted node must not be deleted";
         Node old = nodes[index];
@@ -145,6 +146,7 @@
     }
 
     public void setAndClear(int index, Node clearedNode, int clearedIndex) {
+        assert !self().isDeleted() : "trying to setAndClear successor of deleted node: " + self().shortName();
         assert self().successors == this;
         Node value = clearedNode.successors.get(clearedIndex);
         assert value != Node.Null;
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeBitMap.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeBitMap.java	Fri Jun 10 21:52:19 2011 +0200
@@ -70,6 +70,10 @@
         bitMap.clearAll();
     }
 
+    public void grow(Node node) {
+        bitMap.grow(node.id() + 1);
+    }
+
     private void check(Node node) {
         assert node.graph == graph : "this node is not part of the graph";
         assert !isNew(node) : "this node (" + node.id() + ") was added to the graph after creating the node bitmap (" + bitMap.length() + ")";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeWorkList.java	Fri Jun 10 21:52:19 2011 +0200
@@ -0,0 +1,199 @@
+/*
+ * 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.NoSuchElementException;
+import java.util.Queue;
+
+
+public class NodeWorkList implements Iterable<Node> {
+    private final NodeBitMap visited;
+    private final NodeBitMap inQueue;
+    private final Queue<Node> worklist;
+    private int iterationLimit = Integer.MAX_VALUE;
+
+    NodeWorkList(Graph graph) {
+        this(graph, false, -1);
+    }
+
+    NodeWorkList(Graph graph, boolean fill, int iterationLimitPerNode) {
+        visited = graph.createNodeBitMap();
+        inQueue = graph.createNodeBitMap();
+        if (fill) {
+            ArrayDeque<Node> deque = new ArrayDeque<Node>(graph.getNodeCount());
+            for (Node node : graph.getNodes()) {
+                if (node != null) {
+                    deque.add(node);
+                }
+            }
+            worklist = deque;
+        } else {
+            worklist = new ArrayDeque<Node>();
+        }
+        if (iterationLimitPerNode > 0) {
+            iterationLimit = iterationLimitPerNode * graph.getNodeCount();
+        }
+    }
+
+    public void add(Node node) {
+        if (node != null && !visited.isMarked(node)) {
+            doAdd(node);
+        }
+    }
+
+    private void doAdd(Node node) {
+        if (node != null && !inQueue.isMarked(node)) {
+            visited.mark(node);
+            inQueue.mark(node);
+            worklist.add(node);
+        }
+    }
+
+    public void replaced(Node newNode, Node oldNode, EdgeType... edges) {
+        this.replaced(newNode, oldNode, false, edges);
+    }
+
+    public void replaced(Node newNode, Node oldNode, boolean add, EdgeType... edges) {
+        visited.grow(newNode);
+        inQueue.grow(newNode);
+        worklist.remove(oldNode);
+        assert !worklist.contains(oldNode);
+        if (add) {
+            this.add(newNode);
+        }
+        for (EdgeType type : edges) {
+            switch (type) {
+                case INPUTS:
+                    for (Node n : newNode.inputs()) {
+                        doAdd(n);
+                    }
+                    break;
+                case PREDECESSORS:
+                    for (Node n : newNode.predecessors()) {
+                        doAdd(n);
+                    }
+                    break;
+                case USAGES:
+                    for (Node n : newNode.usages()) {
+                        doAdd(n);
+                    }
+                    break;
+                case SUCCESSORS:
+                    for (Node n : newNode.successors()) {
+                        doAdd(n);
+                    }
+                    break;
+            }
+        }
+    }
+
+    public boolean isMarked(Node node) {
+        return visited.isMarked(node);
+    }
+
+    private class QueueConsumingIterator implements Iterator<Node> {
+        private final Queue<Node> queue;
+
+        public QueueConsumingIterator(Queue<Node> queue) {
+            this.queue = queue;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return iterationLimit > 0 && !queue.isEmpty();
+        }
+
+        @Override
+        public Node next() {
+            if (iterationLimit-- <= 0) {
+                throw new NoSuchElementException();
+            }
+            Node node = queue.remove();
+            inQueue.clear(node);
+            return node;
+        }
+
+        @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.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java	Fri Jun 10 21:52:19 2011 +0200
@@ -621,8 +621,8 @@
             asm.bindOutOfLine(slowPath);
             checkSubtype(asm, objHub, objHub, hub);
             asm.jneq(end, objHub, asm.o(null));
-            XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10);
-            asm.mov(scratch, object);
+            XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10);
+            asm.mov(scratch, asm.createConstant(CiConstant.forWord(0)));
 
             asm.callRuntime(CiRuntimeCall.Deoptimize, null);
             asm.shouldNotReachHere();
@@ -711,6 +711,8 @@
             asm.pload(kind, result, array, index, config.getArrayOffset(kind), Scale.fromInt(elemSize), implicitNullException);
             if (is(BOUNDS_CHECK, flags)) {
                 asm.bindOutOfLine(failBoundsCheck);
+                XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10);
+                asm.mov(scratch, asm.createConstant(CiConstant.forWord(0)));
                 asm.callRuntime(CiRuntimeCall.Deoptimize, null);
                 asm.shouldNotReachHere();
             }
@@ -902,8 +904,8 @@
                 asm.bindOutOfLine(slowStoreCheck);
                 checkSubtype(asm, temp, valueHub, compHub);
                 asm.jneq(store, temp, asm.w(0));
-                XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10);
-                asm.mov(scratch, valueHub);
+                XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10);
+                asm.mov(scratch, asm.createConstant(CiConstant.forWord(0)));
                 asm.callRuntime(CiRuntimeCall.Deoptimize, null);
                 asm.jmp(store);
             }
@@ -986,6 +988,8 @@
             // -- out of line -------------------------------------------------------
             if (is(BOUNDS_CHECK, flags)) {
                 asm.bindOutOfLine(failBoundsCheck);
+                XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10);
+                asm.mov(scratch, asm.createConstant(CiConstant.forWord(0)));
                 asm.callRuntime(CiRuntimeCall.Deoptimize, null);
                 asm.shouldNotReachHere();
             }
@@ -994,8 +998,8 @@
                 asm.bindOutOfLine(slowStoreCheck);
                 checkSubtype(asm, temp, valueHub, compHub);
                 asm.jneq(store, temp, asm.w(0));
-                XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10);
-                asm.mov(scratch, valueHub);
+                XirOperand scratch = asm.createRegisterTemp("scratch", CiKind.Word, AMD64.r10);
+                asm.mov(scratch, asm.createConstant(CiConstant.forWord(0)));
                 asm.callRuntime(CiRuntimeCall.Deoptimize, null);
                 asm.shouldNotReachHere();
             }
--- a/graal/hotspot/hotspot Default.launch	Fri Jun 10 21:51:42 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.cdt.launch.applicationLaunchType">
-<booleanAttribute key="org.eclipse.cdt.dsf.gdb.AUTO_SOLIB" value="true"/>
-<listAttribute key="org.eclipse.cdt.dsf.gdb.AUTO_SOLIB_LIST"/>
-<stringAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_NAME" value="gdb"/>
-<stringAttribute key="org.eclipse.cdt.dsf.gdb.GDB_INIT" value=".gdbinit"/>
-<booleanAttribute key="org.eclipse.cdt.dsf.gdb.NON_STOP" value="false"/>
-<booleanAttribute key="org.eclipse.cdt.dsf.gdb.REVERSE" value="false"/>
-<listAttribute key="org.eclipse.cdt.dsf.gdb.SOLIB_PATH"/>
-<booleanAttribute key="org.eclipse.cdt.dsf.gdb.UPDATE_THREADLIST_ON_SUSPEND" value="false"/>
-<booleanAttribute key="org.eclipse.cdt.dsf.gdb.internal.ui.launching.LocalApplicationCDebuggerTab.DEFAULTS_SET" value="true"/>
-<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/>
-<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
-<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_ID" value="gdb"/>
-<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_START_MODE" value="run"/>
-<booleanAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN" value="true"/>
-<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN_SYMBOL" value="main"/>
-<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_ARGUMENTS" value="-client -XX:+UseC1X -XX:+PrintGC -Xms1g -Xmx1g -Xbootclasspath/p:${workspace_loc:hotspot}/../../../maxine/C1X/bin:${workspace_loc:hotspot}/../../../maxine/com.oracle.max.cri/bin:${workspace_loc:hotspot}/../../../maxine/com.oracle.max.base/bin:${workspace_loc:hotspot}/../../../maxine/com.oracle.max.asmdis/bin:${workspace_loc:hotspot}/../HotSpotVM/bin -classpath ${workspace_loc:hotspot}/../HotSpotTest/bin C1XTest"/>
-<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="java"/>
-<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="hotspot"/>
-<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="cdt.managedbuild.toolchain.gnu.solaris.base.945602881"/>
-<booleanAttribute key="org.eclipse.cdt.launch.use_terminal" value="true"/>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/hotspot"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="4"/>
-</listAttribute>
-<stringAttribute key="org.eclipse.dsf.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;memoryBlockExpressionList context=&quot;reserved-for-future-use&quot;/&gt;&#10;"/>
-</launchConfiguration>
--- a/src/cpu/x86/vm/c1_globals_x86.hpp	Fri Jun 10 21:51:42 2011 +0200
+++ b/src/cpu/x86/vm/c1_globals_x86.hpp	Fri Jun 10 21:52:19 2011 +0200
@@ -40,7 +40,7 @@
 define_pd_global(bool, ProfileTraps,                 false);
 define_pd_global(bool, UseOnStackReplacement,        true );
 define_pd_global(bool, TieredCompilation,            false);
-define_pd_global(intx, CompileThreshold,             1500 );
+define_pd_global(intx, CompileThreshold,             5000 );   // changed for GRAAL
 define_pd_global(intx, BackEdgeThreshold,            100000);
 
 define_pd_global(intx, OnStackReplacePercentage,     933  );
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Fri Jun 10 21:51:42 2011 +0200
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Fri Jun 10 21:52:19 2011 +0200
@@ -140,6 +140,7 @@
   static int rax_offset_in_bytes(void)    { return BytesPerInt * rax_off; }
   static int rdx_offset_in_bytes(void)    { return BytesPerInt * rdx_off; }
   static int rbx_offset_in_bytes(void)    { return BytesPerInt * rbx_off; }
+  static int r10_offset_in_bytes(void)    { return BytesPerInt * r10_off; }
   static int xmm0_offset_in_bytes(void)   { return BytesPerInt * xmm0_off; }
   static int return_offset_in_bytes(void) { return BytesPerInt * return_off; }
 
@@ -2655,6 +2656,7 @@
 
   int jmp_uncommon_trap_offset = __ pc() - start;
   __ pushptr(Address(r15_thread, in_bytes(JavaThread::ScratchA_offset())));
+  __ movptr(rscratch1, 0);
 
   int uncommon_trap_offset = __ pc() - start;
 
@@ -2669,8 +2671,15 @@
   // fetch_unroll_info needs to call last_java_frame()
   __ set_last_Java_frame(noreg, noreg, NULL);
 
-  __ movl(c_rarg1, (int32_t)Deoptimization::Unpack_reexecute);
-  __ movl(r14, c_rarg1); // save into r14 for later call to unpack_frames
+
+  //  __ movl(c_rarg1, (int32_t)Deoptimization::Unpack_reexecute);
+  //  __ movl(r14, c_rarg1); // save into r14 for later call to unpack_frames
+
+  assert(r10 == rscratch1, "scratch register should be r10");
+  __ movptr(c_rarg1, Address(rsp, RegisterSaver::r10_offset_in_bytes()));
+  __ orq(c_rarg1, ~(int32_t)Deoptimization::make_trap_request(Deoptimization::Reason_unreached, Deoptimization::Action_none));
+  __ notq(c_rarg1);
+  __ movl(r14, (int32_t)Deoptimization::Unpack_reexecute);
   __ mov(c_rarg0, r15_thread);
   __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
 
@@ -2744,7 +2753,7 @@
   // or captured in the vframeArray.
   RegisterSaver::restore_result_registers(masm);
 
-  // All of the register save area has been popped of the stack. Only the
+  // All of the register save area has been poppeset_jmp_uncommon_trap_offsetd of the stack. Only the
   // return address remains.
 
   // Pop all the frames we must move/replace.
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java	Fri Jun 10 21:52:19 2011 +0200
@@ -98,7 +98,7 @@
         graph.setBlock(n, this);
         final InputNode node = graph.getNode(id);
         assert node != null;
-        assert !nodes.contains(node);
+        assert !nodes.contains(node) : "duplicate : " + node;
         nodes.add(node);
     }
 
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java	Fri Jun 10 21:51:42 2011 +0200
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java	Fri Jun 10 21:52:19 2011 +0200
@@ -1021,7 +1021,7 @@
 
         for (Figure f : diagram.getFigures()) {
             FigureWidget w = getWidget(f);
-            if (w.isVisible()) {
+            if (w != null && w.isVisible()) {
                 oldVisibleWidgets.add(w);
             }
         }
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Fri Jun 10 21:51:42 2011 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Fri Jun 10 21:52:19 2011 +0200
@@ -106,7 +106,8 @@
 }
 
 // TODO: finish this - graal doesn't provide any scope values at the moment
-static ScopeValue* get_hotspot_value(oop value, int frame_size) {
+static ScopeValue* get_hotspot_value(oop value, int frame_size, ScopeValue* &second) {
+  second = NULL;
   if (value == CiValue::IllegalValue()) {
     return new LocationValue(Location::new_stk_loc(Location::invalid, 0));
   }
@@ -114,27 +115,61 @@
   BasicType type = GraalCompiler::kindToBasicType(CiKind::typeChar(CiValue::kind(value)));
   Location::Type locationType = Location::normal;
   if (type == T_OBJECT || type == T_ARRAY) locationType = Location::oop;
+
   if (value->is_a(CiRegisterValue::klass())) {
     jint number = CiRegister::number(CiRegisterValue::reg(value));
     if (number < 16) {
-      return new LocationValue(Location::new_reg_loc(locationType, as_Register(number)->as_VMReg()));
+      if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BOOLEAN || type == T_BYTE) {
+        locationType = Location::int_in_long;
+      } else if (type == T_LONG) {
+        locationType = Location::lng;
+      } else {
+        assert(type == T_OBJECT || type == T_ARRAY, "unexpected type in cpu register");
+      }
+      ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_Register(number)->as_VMReg()));
+      if (type == T_LONG) {
+        second = value;
+      }
+      return value;
     } else {
-      return new LocationValue(Location::new_reg_loc(locationType, as_XMMRegister(number - 16)->as_VMReg()));
+      assert(type == T_FLOAT || type == T_DOUBLE, "only float and double expected in xmm register");
+      if (type == T_FLOAT) {
+        // this seems weird, but the same value is used in c1_LinearScan
+        locationType = Location::normal;
+      } else {
+        locationType = Location::dbl;
+      }
+      ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_XMMRegister(number - 16)->as_VMReg()));
+      if (type == T_DOUBLE) {
+        second = value;
+      }
+      return value;
     }
   } else if (value->is_a(CiStackSlot::klass())) {
+    if (type == T_DOUBLE) {
+      locationType = Location::dbl;
+    } else if (type == T_LONG) {
+      locationType = Location::lng;
+    }
     jint index = CiStackSlot::index(value);
+    ScopeValue* value;
     if (index >= 0) {
-      return new LocationValue(Location::new_stk_loc(locationType, index * HeapWordSize));
+      value = new LocationValue(Location::new_stk_loc(locationType, index * HeapWordSize));
     } else {
       int frame_size_bytes = frame_size + 2 * HeapWordSize;
-      return new LocationValue(Location::new_stk_loc(locationType, -(index * HeapWordSize) + frame_size_bytes));
+      value = new LocationValue(Location::new_stk_loc(locationType, -(index * HeapWordSize) + frame_size_bytes));
     }
+    if (type == T_DOUBLE || type == T_LONG) {
+      second = value;
+    }
+    return value;
   } else if (value->is_a(CiConstant::klass())){
     oop obj = CiConstant::object(value);
     jlong prim = CiConstant::primitive(value);
     if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BOOLEAN || type == T_BYTE) {
       return new ConstantIntValue(*(jint*)&prim);
     } else if (type == T_LONG || type == T_DOUBLE) {
+      second = new ConstantIntValue(0);
       return new ConstantLongValue(prim);
     } else if (type == T_OBJECT) {
       oop obj = CiConstant::object(value);
@@ -433,19 +468,32 @@
     }
 
     for (jint i = 0; i < values->length(); i++) {
-      ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], _frame_size);
+      ScopeValue* second = NULL;
+      ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], _frame_size, second);
 
       if (i < local_count) {
+        if (second != NULL) {
+          locals->append(second);
+        }
         locals->append(value);
       } else if (i < local_count + expression_count) {
+        if (second != NULL) {
+          expressions->append(value);
+        }
         expressions->append(value);
       } else {
+        assert(second == NULL, "monitor cannot occupy two stack slots");
         assert(value->is_location(), "invalid monitor location");
         LocationValue* loc = (LocationValue*)value;
         int monitor_offset = loc->location().stack_offset();
         LocationValue* obj = new LocationValue(Location::new_stk_loc(Location::oop, monitor_offset + BasicObjectLock::obj_offset_in_bytes()));
         monitors->append(new MonitorValue(obj, Location::new_stk_loc(Location::normal, monitor_offset  + BasicObjectLock::lock_offset_in_bytes())));
       }
+      if (second != NULL) {
+        i++;
+        assert(i < values->length(), "double-slot value not followed by CiValue.IllegalValue");
+        assert(((oop*) values->base(T_OBJECT))[i] == CiValue::IllegalValue(), "double-slot value not followed by CiValue.IllegalValue");
+      }
     }
     DebugToken* locals_token = _debug_recorder->create_scope_values(locals);
     DebugToken* expressions_token = _debug_recorder->create_scope_values(expressions);
--- a/src/share/vm/oops/methodOop.cpp	Fri Jun 10 21:51:42 2011 +0200
+++ b/src/share/vm/oops/methodOop.cpp	Fri Jun 10 21:52:19 2011 +0200
@@ -206,6 +206,12 @@
 }
 
 address methodOopDesc::bcp_from(int bci) const {
+#ifdef ASSERT
+  if (!((is_native() && bci == 0)  || (!is_native() && 0 <= bci && bci < code_size()))) {
+    char buf[1024];
+    tty->print_cr("bci: %i, size: %i, method: %s", bci, code_size(), const_cast<methodOop>(this)->name_and_sig_as_C_string(buf, 1024));
+  }
+#endif // ASSERT
   assert((is_native() && bci == 0)  || (!is_native() && 0 <= bci && bci < code_size()), "illegal bci");
   address bcp = code_base() + bci;
   assert(is_native() && bcp == code_base() || contains(bcp), "bcp doesn't belong to this method");
--- a/src/share/vm/runtime/deoptimization.cpp	Fri Jun 10 21:51:42 2011 +0200
+++ b/src/share/vm/runtime/deoptimization.cpp	Fri Jun 10 21:52:19 2011 +0200
@@ -1221,6 +1221,8 @@
     DeoptAction action = trap_request_action(trap_request);
     jint unloaded_class_index = trap_request_index(trap_request); // CP idx or -1
 
+//    tty->print_cr("trap_request: %08x, cpi: %i, pc: %016x", trap_request, unloaded_class_index, fr.pc());
+
     Events::log("Uncommon trap occurred @" INTPTR_FORMAT " unloaded_class_index = %d", fr.pc(), (int) trap_request);
     vframe*  vf  = vframe::new_vframe(&fr, &reg_map, thread);
     compiledVFrame* cvf = compiledVFrame::cast(vf);