changeset 3165:ce7e5b3798f7

merge
author Lukas Stadler <lukas.stadler@jku.at>
date Wed, 06 Jul 2011 16:51:01 +0200
parents 2b1eace223b0 (current diff) 8044bdfaab06 (diff)
children adbb7bca84b7
files 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/ir/CheckCast.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CreateVectorNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionDispatch.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NotInstanceOf.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java
diffstat 66 files changed, 1831 insertions(+), 903 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Wed Jul 06 16:51:01 2011 +0200
@@ -52,10 +52,9 @@
     public final RiMethod method;
     public final RiRegisterConfig registerConfig;
     public final CiStatistics stats;
-    public final CiAssumptions assumptions = new CiAssumptions();
     public final FrameState placeholderState;
 
-    public CompilerGraph graph = new CompilerGraph(this);
+    public final CompilerGraph graph;
 
     private boolean hasExceptionHandlers;
     private final GraalCompilation parent;
@@ -92,6 +91,7 @@
         this.compiler = compiler;
         this.target = compiler.target;
         this.runtime = compiler.runtime;
+        this.graph = new CompilerGraph(runtime);
         this.method = method;
         this.stats = stats == null ? new CiStatistics() : stats;
         this.registerConfig = method == null ? compiler.globalStubRegisterConfig : runtime.getRegisterConfig(method);
@@ -139,16 +139,6 @@
     }
 
     /**
-     * Records an assumption that the specified type has no finalizable subclasses.
-     *
-     * @param receiverType the type that is assumed to have no finalizable subclasses
-     * @return {@code true} if the assumption was recorded and can be assumed; {@code false} otherwise
-     */
-    public boolean recordNoFinalizableSubclassAssumption(RiType receiverType) {
-        return false;
-    }
-
-    /**
      * Converts this compilation to a string.
      *
      * @return a string representation of this compilation
@@ -285,8 +275,8 @@
             lirAssembler.emitTraps();
 
             CiTargetMethod targetMethod = assembler().finishTargetMethod(method, runtime, lirAssembler.registerRestoreEpilogueOffset, false);
-            if (assumptions.count() > 0) {
-                targetMethod.setAssumptions(assumptions);
+            if (graph.assumptions().count() > 0) {
+                targetMethod.setAssumptions(graph.assumptions());
             }
 
             if (compiler.isObserved()) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Wed Jul 06 16:51:01 2011 +0200
@@ -153,8 +153,10 @@
     public static boolean CommentedAssembly                  = ____;
     public static boolean PrintLIRWithAssembly               = ____;
 
+    public static boolean OptReadElimination                 = ____;
     public static boolean OptGVN                             = ____;
     public static boolean OptCanonicalizer                   = true;
     public static boolean OptLoops                           = ____;
+    public static boolean OptOptimisticSchedule              = ____;
     public static boolean LoopPeeling                        = ____;
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Wed Jul 06 16:51:01 2011 +0200
@@ -203,6 +203,10 @@
         this.operands = new OperandPool(compilation.target);
     }
 
+    public CiTarget target() {
+        return compilation.target;
+    }
+
     public LIRList lir() {
         return lir;
     }
@@ -476,19 +480,14 @@
     }
 
     public void emitBooleanBranch(Node node, LIRBlock trueSuccessor, LIRBlock falseSuccessor, LIRDebugInfo info) {
-        if (node instanceof Compare) {
+        if (node instanceof NegateBooleanNode) {
+            emitBooleanBranch(((NegateBooleanNode) node).value(), falseSuccessor, trueSuccessor, info);
+        } else if (node instanceof Compare) {
             emitCompare((Compare) node, trueSuccessor, falseSuccessor);
         } else if (node instanceof InstanceOf) {
             emitInstanceOf((TypeCheck) node, trueSuccessor, falseSuccessor, info);
-        } else if (node instanceof NotInstanceOf) {
-            emitInstanceOf((TypeCheck) node, falseSuccessor, trueSuccessor, info);
         } else if (node instanceof Constant) {
-            CiConstant constant = ((Constant) node).asConstant();
-            assert constant.kind == CiKind.Boolean;
-            LIRBlock target = constant.asBoolean() ? trueSuccessor : falseSuccessor;
-            if (target != null) {
-                lir.jump(target);
-            }
+            emitConstantBranch(((Constant) node).asConstant().asBoolean(), trueSuccessor, falseSuccessor, info);
         } else {
             throw Util.unimplemented(node.toString());
         }
@@ -503,6 +502,21 @@
         instr.setFalseSuccessor(falseSuccessor);
     }
 
+
+    public void emitConstantBranch(boolean value, LIRBlock trueSuccessorBlock, LIRBlock falseSuccessorBlock, LIRDebugInfo info) {
+        if (value) {
+            emitConstantBranch(trueSuccessorBlock, info);
+        } else {
+            emitConstantBranch(falseSuccessorBlock, info);
+        }
+    }
+
+    private void emitConstantBranch(LIRBlock block, LIRDebugInfo info) {
+        if (block != null) {
+            lir.jump(block);
+        }
+    }
+
     public void emitCompare(Compare compare, LIRBlock trueSuccessorBlock, LIRBlock falseSuccessorBlock) {
         CiKind kind = compare.x().kind;
 
@@ -585,20 +599,11 @@
     }
 
     protected FrameState stateBeforeInvokeReturn(Invoke invoke) {
-        return invoke.stateAfter().duplicateModified(getBeforeInvokeBci(invoke), invoke.stateAfter().rethrowException(), invoke.kind);
+        return invoke.stateAfter().duplicateModified(invoke.bci, invoke.stateAfter().rethrowException(), invoke.kind);
     }
 
     protected FrameState stateBeforeInvokeWithArguments(Invoke invoke) {
-        Value[] args = new Value[invoke.argumentCount()];
-        for (int i = 0; i < invoke.argumentCount(); i++) {
-            args[i] = invoke.argument(i);
-        }
-        return invoke.stateAfter().duplicateModified(getBeforeInvokeBci(invoke), invoke.stateAfter().rethrowException(), invoke.kind, args);
-    }
-
-    private int getBeforeInvokeBci(Invoke invoke) {
-        // Cannot calculate BCI, because the invoke can have changed from e.g. invokeinterface to invokespecial because of optimizations.
-        return invoke.bci;
+        return invoke.stateAfter().duplicateModified(invoke.bci, invoke.stateAfter().rethrowException(), invoke.kind, invoke.arguments().toArray(new Value[0]));
     }
 
     @Override
@@ -751,8 +756,11 @@
 
     @Override
     public void visitFixedGuard(FixedGuard fixedGuard) {
-        BooleanNode comp = fixedGuard.node();
-        emitGuardComp(comp);
+        for (Node n : fixedGuard.inputs()) {
+            if (n != null) {
+                emitGuardComp((BooleanNode) n);
+    }
+        }
     }
 
     public void emitGuardComp(BooleanNode comp) {
@@ -772,14 +780,18 @@
             FrameState state = lastState;
             assert state != null : "deoptimize instruction always needs a state";
 
+            if (comp instanceof Constant && comp.asConstant().asBoolean()) {
+                // Nothing to emit.
+            } else {
             if (deoptimizationStubs == null) {
                 deoptimizationStubs = new ArrayList<DeoptimizationStub>();
             }
+
             DeoptimizationStub stub = new DeoptimizationStub(DeoptAction.InvalidateReprofile, state);
             deoptimizationStubs.add(stub);
-
             emitBooleanBranch(comp, null, new LIRBlock(stub.label, stub.info), stub.info);
         }
+        }
     }
 
     @Override
@@ -1103,7 +1115,7 @@
      * @return the operand that is guaranteed to be a stack location when it is
      *         initially defined a by move from {@code value}
      */
-    CiValue forceToSpill(CiValue value, CiKind kind, boolean mustStayOnStack) {
+    public CiValue forceToSpill(CiValue value, CiKind kind, boolean mustStayOnStack) {
         assert value.isLegal() : "value should not be illegal";
         assert kind.jvmSlots == value.kind.jvmSlots : "size mismatch";
         if (!value.isVariableOrRegister()) {
@@ -1470,8 +1482,11 @@
     @Override
     public void visitEndNode(EndNode end) {
         setNoResult(end);
+        assert end.merge() != null;
         moveToPhi(end.merge(), end);
-        lir.jump(getLIRBlock(end.merge()));
+        LIRBlock lirBlock = getLIRBlock(end.merge());
+        assert lirBlock != null : end;
+        lir.jump(lirBlock);
     }
 
     @Override
@@ -1584,7 +1599,7 @@
         x.clearOperand();
     }
 
-    protected CiValue setResult(Value x, CiVariable operand) {
+    public CiValue setResult(Value x, CiVariable operand) {
         x.setOperand(operand);
         if (GraalOptions.DetailedAsserts) {
             operands.recordResult(operand, x);
@@ -1653,10 +1668,9 @@
 
     List<CiValue> visitInvokeArguments(CiCallingConvention cc, Invoke x, List<CiValue> pointerSlots) {
         // for each argument, load it into the correct location
-        List<CiValue> argList = new ArrayList<CiValue>(x.argumentCount());
+        List<CiValue> argList = new ArrayList<CiValue>();
         int j = 0;
-        for (int i = 0; i < x.argumentCount(); i++) {
-            Value arg = x.argument(i);
+        for (Value arg : x.arguments()) {
             if (arg != null) {
                 CiValue operand = cc.locations[j++];
                 if (operand.isRegister()) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java	Wed Jul 06 16:51:01 2011 +0200
@@ -126,7 +126,7 @@
         final HashSet<Block> successors = new LinkedHashSet<Block>();
         private boolean visited;
         private boolean active;
-        private int loops;
+        private long loops;
     }
 
     public static class ExceptionBlock  extends Block {
@@ -485,7 +485,7 @@
     }
 
     private void computeBlockOrder() {
-        int loop = computeBlockOrder(blockMap[0]);
+        long loop = computeBlockOrder(blockMap[0]);
 
         if (loop != 0) {
             // There is a path from a loop end to the method entry that does not pass the loop header.
@@ -501,7 +501,7 @@
     /**
      * The next available loop number.
      */
-    private int nextLoop = 0;
+    private int nextLoop;
 
     /**
      * Mark the block as a loop header, using the next available loop number.
@@ -516,7 +516,7 @@
                 // Don't compile such methods for now, until we see a concrete case that allows checking for correctness.
                 throw new CiBailout("Loop formed by an exception handler");
             }
-            if (nextLoop >= Integer.SIZE) {
+            if (nextLoop >= Long.SIZE) {
                 // This restriction can be removed by using a fall-back to a BitSet in case we have more than 32 loops
                 // Don't compile such methods for now, until we see a concrete case that allows checking for correctness.
                 throw new CiBailout("Too many loops in method");
@@ -526,7 +526,7 @@
             block.loops = 1 << nextLoop;
             nextLoop++;
         }
-        assert Integer.bitCount(block.loops) == 1;
+        assert Long.bitCount(block.loops) == 1;
     }
 
     /**
@@ -534,7 +534,7 @@
      * visit every block only once. The flag {@linkplain Block#active} is used to detect cycles (backward
      * edges).
      */
-    private int computeBlockOrder(Block block) {
+    private long computeBlockOrder(Block block) {
         if (block.visited) {
             if (block.active) {
                 // Reached block via backward branch.
@@ -557,7 +557,7 @@
             processLoopBlock(block);
         }
         if (block.isLoopHeader) {
-            assert Integer.bitCount(block.loops) == 1;
+            assert Long.bitCount(block.loops) == 1;
             loops &= ~block.loops;
         }
 
@@ -694,6 +694,6 @@
         }
         out.println();
 
-        out.print("loop_depth ").println(Integer.bitCount(block.loops));
+        out.print("loop_depth ").println(Long.bitCount(block.loops));
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/CompilerGraph.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/CompilerGraph.java	Wed Jul 06 16:51:01 2011 +0200
@@ -22,21 +22,22 @@
  */
 package com.oracle.max.graal.compiler.graph;
 
-import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
 
 
 public class CompilerGraph extends Graph {
 
+    private RiRuntime runtime;
     private Return returnSingleton;
     private Unwind unwindSingleton;
-    private GraalCompilation compilation;
+    private CiAssumptions assumptions = new CiAssumptions();
 
 
-    public CompilerGraph(GraalCompilation compilation) {
-        this.compilation = compilation;
+    public CompilerGraph(RiRuntime runtime) {
+        this.runtime = runtime;
     }
 
     public void setReturn(Return returnNode) {
@@ -58,10 +59,10 @@
     }
 
     public RiRuntime runtime() {
-        return compilation.runtime;
+        return runtime;
     }
 
-    public GraalCompilation getCompilation() {
-        return compilation;
+    public CiAssumptions assumptions() {
+        return assumptions;
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Wed Jul 06 16:51:01 2011 +0200
@@ -76,18 +76,15 @@
 //            replacements.put(duplicate.start(), compilation.graph.start());
 //            compilation.graph.addDuplicate(duplicate.getNodes(), replacements);
 //        } else {
-            new GraphBuilderPhase(compilation, compilation.method, false, false).apply(compilation.graph);
+            new GraphBuilderPhase(compilation, compilation.method, false).apply(compilation.graph);
 //        }
 
-        //printGraph("After GraphBuilding", compilation.graph);
 
         if (GraalOptions.TestGraphDuplication) {
             new DuplicationPhase().apply(compilation.graph);
-            //printGraph("After Duplication", compilation.graph);
         }
 
         new DeadCodeEliminationPhase().apply(compilation.graph);
-        //printGraph("After DeadCodeElimination", compilation.graph);
 
         if (GraalOptions.Inline) {
             new InliningPhase(compilation, this, null).apply(compilation.graph);
@@ -104,9 +101,8 @@
             new LoopPhase().apply(graph);
         }
 
-        if (GraalOptions.EscapeAnalysis /*&& compilation.method.toString().contains("simplify")*/) {
+        if (GraalOptions.EscapeAnalysis) {
             new EscapeAnalysisPhase(compilation, this).apply(graph);
-         //   new DeadCodeEliminationPhase().apply(graph);
             new CanonicalizerPhase().apply(graph);
             new DeadCodeEliminationPhase().apply(graph);
         }
@@ -115,17 +111,20 @@
             new GlobalValueNumberingPhase().apply(graph);
         }
 
+        new LoweringPhase(compilation.runtime).apply(graph);
         if (GraalOptions.Lower) {
-            new LoweringPhase(compilation.runtime).apply(graph);
             new MemoryPhase().apply(graph);
             if (GraalOptions.OptGVN) {
                 new GlobalValueNumberingPhase().apply(graph);
             }
-            new ReadEliminationPhase().apply(graph);
+            if (GraalOptions.OptReadElimination) {
+                new ReadEliminationPhase().apply(graph);
+            }
         }
 
         IdentifyBlocksPhase schedule = new IdentifyBlocksPhase(true);
         schedule.apply(graph);
+        compilation.stats.loopCount = schedule.loopCount();
 
 
         List<Block> blocks = schedule.getBlocks();
@@ -136,6 +135,8 @@
             map.put(b, block);
             block.setInstructions(b.getInstructions());
             block.setLinearScanNumber(b.blockID());
+            block.setLoopDepth(b.loopDepth());
+            block.setLoopIndex(b.loopIndex());
 
             block.setFirstInstruction(b.firstNode());
             block.setLastInstruction(b.lastNode());
@@ -170,7 +171,6 @@
 
         ComputeLinearScanOrder clso = new ComputeLinearScanOrder(lirBlocks.size(), startBlock);
         orderedBlocks = clso.linearScanOrder();
-        this.compilation.stats.loopCount = clso.numLoops();
 
         int z = 0;
         for (LIRBlock b : orderedBlocks) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractVectorNode.java	Wed Jul 06 16:51:01 2011 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class AbstractVectorNode extends StateSplit {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VECTOR = 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;
+    }
+
+    public void setVector(AbstractVectorNode length) {
+        inputs().set(super.inputCount() + INPUT_VECTOR, length);
+    }
+
+    public AbstractVectorNode vector() {
+        return (AbstractVectorNode) inputs().get(super.inputCount() + INPUT_VECTOR);
+    }
+
+    public AbstractVectorNode(CiKind kind, int inputCount, int successorCount, AbstractVectorNode vector, Graph graph) {
+        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+        setVector(vector);
+    }
+
+    protected static AbstractVectorNode findCommonNode(AbstractVectorNode left, AbstractVectorNode right, List<AbstractVectorNode> leftList, List<AbstractVectorNode> rightList) {
+        Set<AbstractVectorNode> occured = new HashSet<AbstractVectorNode>();
+        AbstractVectorNode common = null;
+        AbstractVectorNode cur = left;
+        while (cur != null) {
+            occured.add(cur);
+            cur = cur.vector();
+        }
+
+        cur = right;
+        while (cur != null) {
+            if (occured.contains(cur)) {
+                common = cur;
+                break;
+            }
+            cur = cur.vector();
+        }
+
+        fillUntil(left, cur, leftList);
+        fillUntil(right, cur, rightList);
+        return common;
+    }
+
+    private static void fillUntil(AbstractVectorNode left, AbstractVectorNode until, List<AbstractVectorNode> leftList) {
+        AbstractVectorNode cur = left;
+        while (cur != null && cur != until) {
+            leftList.add(cur);
+            cur = cur.vector();
+        }
+    }
+
+    public void addToLoop(LoopBegin loop, IdentityHashMap<AbstractVectorNode, Value> nodes) {
+        throw new IllegalStateException("unimplemented");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessVectorNode.java	Wed Jul 06 16:51:01 2011 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class AccessVectorNode extends AbstractVectorNode {
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_OBJECT = 0;
+    private static final int INPUT_LOCATION = 1;
+    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;
+    }
+
+    public void setObject(Value object) {
+        inputs().set(super.inputCount() + INPUT_OBJECT, object);
+    }
+
+    public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public void setLocation(LocationNode object) {
+        inputs().set(super.inputCount() + INPUT_LOCATION, object);
+    }
+
+    public LocationNode location() {
+        return (LocationNode) inputs().get(super.inputCount() + INPUT_LOCATION);
+    }
+
+    public AccessVectorNode(CiKind kind, int inputCount, int successorCount, AbstractVectorNode vector, Value object, LocationNode location, Graph graph) {
+        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, vector, graph);
+        setObject(object);
+        setLocation(location);
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java	Wed Jul 06 16:51:01 2011 +0200
@@ -95,8 +95,7 @@
 
     @Override
     public Node copy(Graph into) {
-        ArrayLength x = new ArrayLength(null, into);
-        return x;
+        return new ArrayLength(null, into);
     }
 
     @SuppressWarnings("unchecked")
@@ -128,7 +127,7 @@
             if (constantValue != null && constantValue.isNonNull()) {
                 Graph graph = node.graph();
                 if (graph instanceof CompilerGraph) {
-                    RiRuntime runtime = ((CompilerGraph) graph).getCompilation().runtime;
+                    RiRuntime runtime = ((CompilerGraph) graph).runtime();
                     return Constant.forInt(runtime.getArrayLength(constantValue), graph);
                 }
             }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BooleanNode.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BooleanNode.java	Wed Jul 06 16:51:01 2011 +0200
@@ -31,9 +31,4 @@
     public BooleanNode(CiKind kind, int inputCount, int successorCount, Graph graph) {
         super(kind, inputCount, successorCount, graph);
     }
-
-
-    public BooleanNode negate() {
-        throw new IllegalStateException();
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CastNode.java	Wed Jul 06 16:51:01 2011 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class CastNode extends FloatingNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_NODE = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+    public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_NODE);
+    }
+
+    public void setValue(Value n) {
+        inputs().set(super.inputCount() + INPUT_NODE, n);
+    }
+
+    public CastNode(CiKind kind, Value n, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setValue(n);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) new LIRGenerator.LIRGeneratorOp() {
+                @Override
+                public void generate(Node n, LIRGenerator generator) {
+                    CastNode conv = (CastNode) n;
+                    conv.setOperand(generator.load(conv.value()));
+                }
+            };
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("cast node ").print(value().toString());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new CastNode(kind, null, into);
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java	Wed Jul 06 16:51:01 2011 +0200
@@ -43,7 +43,7 @@
      * @param object the instruction producing the object
      * @param graph
      */
-    public CheckCast(Constant targetClassInstruction, Value object, Graph graph) {
+    public CheckCast(Value targetClassInstruction, Value object, Graph graph) {
         super(targetClassInstruction, object, CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
@@ -92,8 +92,7 @@
 
     @Override
     public Node copy(Graph into) {
-        CheckCast x = new CheckCast(null, null, into);
-        return x;
+        return new CheckCast(null, null, into);
     }
 
     private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java	Wed Jul 06 16:51:01 2011 +0200
@@ -157,11 +157,6 @@
         return x;
     }
 
-    @Override
-    public BooleanNode negate() {
-        return new Compare(x(), condition.negate(), y(), graph());
-    }
-
     private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
         @Override
         public Node canonical(Node node) {
@@ -197,7 +192,7 @@
                     }
                     BooleanNode result = materializeNode.value();
                     if (isFalseCheck) {
-                        result = result.negate();
+                        result = new NegateBooleanNode(result, compare.graph());
                     }
                     if (GraalOptions.TraceCanonicalizer) {
                         TTY.println("Removed materialize replacing with " + result);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ComputeLinearScanOrder.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ComputeLinearScanOrder.java	Wed Jul 06 16:51:01 2011 +0200
@@ -28,16 +28,12 @@
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
-import com.sun.cri.ci.*;
 
 public final class ComputeLinearScanOrder {
 
     private final int maxBlockId; // the highest blockId of a block
     private int numBlocks; // total number of blocks (smaller than maxBlockId)
-    private int numLoops; // total number of loops
-    private boolean iterativeDominators; // method requires iterative computation of dominators
 
     List<LIRBlock> linearScanOrder; // the resulting list of blocks in correct order
 
@@ -45,8 +41,6 @@
     final BitMap activeBlocks; // used for recursive processing of blocks
     final BitMap dominatorBlocks; // temporary BitMap used for computation of dominator
     final int[] forwardBranches; // number of incoming forward branches for each block
-    final List<LIRBlock> loopEndBlocks; // list of all loop end blocks collected during countEdges
-    BitMap2D loopMap; // two-dimensional bit set: a bit is set if a block is contained in a loop
     final List<LIRBlock> workList; // temporary list (used in markLoops and computeOrder)
 
     // accessors for visitedBlocks and activeBlocks
@@ -87,28 +81,11 @@
         return --forwardBranches[b.blockID()];
     }
 
-    // accessors for loopMap
-    boolean isBlockInLoop(int loopIdx, LIRBlock b) {
-        return loopMap.at(loopIdx, b.blockID());
-    }
-
-    void setBlockInLoop(int loopIdx, LIRBlock b) {
-        loopMap.setBit(loopIdx, b.blockID());
-    }
-
-    void clearBlockInLoop(int loopIdx, int blockId) {
-        loopMap.clearBit(loopIdx, blockId);
-    }
-
     // accessors for final result
     public List<LIRBlock> linearScanOrder() {
         return linearScanOrder;
     }
 
-    public int numLoops() {
-        return numLoops;
-    }
-
     public ComputeLinearScanOrder(int maxBlockId, LIRBlock startBlock) {
 
         this.maxBlockId = maxBlockId;
@@ -116,27 +93,11 @@
         activeBlocks = new BitMap(maxBlockId);
         dominatorBlocks = new BitMap(maxBlockId);
         forwardBranches = new int[maxBlockId];
-        loopEndBlocks = new ArrayList<LIRBlock>(8);
         workList = new ArrayList<LIRBlock>(8);
 
-        splitCriticalEdges();
-
         countEdges(startBlock, null);
-
-        if (numLoops > 0) {
-            markLoops();
-            clearNonNaturalLoops(startBlock);
-            assignLoopDepth(startBlock);
-        }
-
         computeOrder(startBlock);
-
         printBlocks();
-        assert verify();
-    }
-
-    void splitCriticalEdges() {
-        // TODO: move critical edge splitting from IR to here
     }
 
     /**
@@ -153,16 +114,6 @@
         }
 
         if (isActive(cur)) {
-            if (GraalOptions.TraceLinearScanLevel >= 3) {
-                TTY.println("backward branch");
-            }
-            assert isVisited(cur) : "block must be visited when block is active";
-            assert parent != null : "must have parent";
-
-            cur.setLinearScanLoopHeader();
-            parent.setLinearScanLoopEnd();
-
-            loopEndBlocks.add(parent);
             return;
         }
 
@@ -188,137 +139,11 @@
 
         clearActive(cur);
 
-        // Each loop has a unique number.
-        // When multiple loops are nested, assignLoopDepth assumes that the
-        // innermost loop has the lowest number. This is guaranteed by setting
-        // the loop number after the recursive calls for the successors above
-        // have returned.
-        if (cur.isLinearScanLoopHeader()) {
-            assert cur.loopIndex() == -1 : "cannot set loop-index twice";
-            if (GraalOptions.TraceLinearScanLevel >= 3) {
-                TTY.println("Block B%d is loop header of loop %d", cur.blockID(), numLoops);
-            }
-
-            cur.setLoopIndex(numLoops);
-            numLoops++;
-        }
-
         if (GraalOptions.TraceLinearScanLevel >= 3) {
             TTY.println("Finished counting edges for block B%d", cur.blockID());
         }
     }
 
-    void markLoops() {
-        if (GraalOptions.TraceLinearScanLevel >= 3) {
-            TTY.println("----- marking loops");
-        }
-
-        loopMap = new BitMap2D(numLoops, maxBlockId);
-
-        for (int i = loopEndBlocks.size() - 1; i >= 0; i--) {
-            LIRBlock loopEnd = loopEndBlocks.get(i);
-            LIRBlock loopStart = loopEnd.suxAt(0);
-            int loopIdx = loopStart.loopIndex();
-
-            if (GraalOptions.TraceLinearScanLevel >= 3) {
-                TTY.println("Processing loop from B%d to B%d (loop %d):", loopStart.blockID(), loopEnd.blockID(), loopIdx);
-            }
-            assert loopEnd.isLinearScanLoopEnd() : "loop end flag must be set";
-//            assert loopEnd.numberOfSux() == 1 : "incorrect number of successors";
-            assert loopStart.isLinearScanLoopHeader() : "loop header flag must be set";
-            assert loopIdx >= 0 && loopIdx < numLoops : "loop index not set";
-            assert workList.isEmpty() : "work list must be empty before processing";
-
-            // add the end-block of the loop to the working list
-            workList.add(loopEnd);
-            setBlockInLoop(loopIdx, loopEnd);
-            do {
-                LIRBlock cur = workList.remove(workList.size() - 1);
-
-                if (GraalOptions.TraceLinearScanLevel >= 3) {
-                    TTY.println("    processing B%d", cur.blockID());
-                }
-                assert isBlockInLoop(loopIdx, cur) : "bit in loop map must be set when block is in work list";
-
-                // recursive processing of all predecessors ends when start block of loop is reached
-                if (cur != loopStart) {
-                    for (int j = cur.numberOfPreds() - 1; j >= 0; j--) {
-                        LIRBlock pred = cur.predAt(j);
-
-                        if (!isBlockInLoop(loopIdx, pred)) {
-                            // this predecessor has not been processed yet, so add it to work list
-                            if (GraalOptions.TraceLinearScanLevel >= 3) {
-                                TTY.println("    pushing B%d", pred.blockID());
-                            }
-                            workList.add(pred);
-                            setBlockInLoop(loopIdx, pred);
-                        }
-                    }
-                }
-            } while (!workList.isEmpty());
-        }
-    }
-
-    // check for non-natural loops (loops where the loop header does not dominate
-    // all other loop blocks = loops with multiple entries).
-    // such loops are ignored
-    void clearNonNaturalLoops(LIRBlock startBlock) {
-        for (int i = numLoops - 1; i >= 0; i--) {
-            if (isBlockInLoop(i, startBlock)) {
-                // loop i contains the entry block of the method.
-                // this is not a natural loop, so ignore it
-                if (GraalOptions.TraceLinearScanLevel >= 2) {
-                    TTY.println("Loop %d is non-natural, so it is ignored", i);
-                }
-
-                for (int blockId = maxBlockId - 1; blockId >= 0; blockId--) {
-                    clearBlockInLoop(i, blockId);
-                }
-                iterativeDominators = true;
-            }
-        }
-    }
-
-    void assignLoopDepth(LIRBlock startBlock) {
-        if (GraalOptions.TraceLinearScanLevel >= 3) {
-            TTY.println("----- computing loop-depth and weight");
-        }
-        initVisited();
-
-        assert workList.isEmpty() : "work list must be empty before processing";
-        workList.add(startBlock);
-
-        do {
-            LIRBlock cur = workList.remove(workList.size() - 1);
-
-            if (!isVisited(cur)) {
-                setVisited(cur);
-                if (GraalOptions.TraceLinearScanLevel >= 4) {
-                    TTY.println("Computing loop depth for block B%d", cur.blockID());
-                }
-
-                // compute loop-depth and loop-index for the block
-                assert cur.loopDepth() == 0 : "cannot set loop-depth twice";
-                int i;
-                int loopDepth = 0;
-                int minLoopIdx = -1;
-                for (i = numLoops - 1; i >= 0; i--) {
-                    if (isBlockInLoop(i, cur)) {
-                        loopDepth++;
-                        minLoopIdx = i;
-                    }
-                }
-                cur.setLoopDepth(loopDepth);
-                cur.setLoopIndex(minLoopIdx);
-
-                // append all unvisited successors to work list
-                for (i = cur.numberOfSux() - 1; i >= 0; i--) {
-                    workList.add(cur.suxAt(i));
-                }
-            }
-        } while (!workList.isEmpty());
-    }
-
     int computeWeight(LIRBlock cur) {
 
         // limit loop-depth to 15 bit (only for security reason, it will never be so big)
@@ -329,10 +154,10 @@
         // this is necessary for the (very rare) case that two successive blocks have
         // the same loop depth, but a different loop index (can happen for endless loops
         // with exception handlers)
-        if (!cur.isLinearScanLoopHeader()) {
-            weight |= 1 << curBit;
-        }
-        curBit--;
+//        if (!cur.isLinearScanLoopHeader()) {
+//            weight |= 1 << curBit;
+//        }
+//        curBit--;
 
         // loop end blocks (blocks that end with a backward branch) are added
         // after all other blocks of the loop.
@@ -360,10 +185,10 @@
 //        curBit--;
 
         // exceptions handlers are added as late as possible
-//        if (!cur.isExceptionEntry()) {
-//            weight |= 1 << curBit;
-//        }
-//        curBit--;
+        if (!cur.isExceptionEntry()) {
+            weight |= 1 << curBit;
+        }
+        curBit--;
 
         // guarantee that weight is > 0
         weight |= 1;
@@ -374,7 +199,7 @@
         return weight;
     }
 
-    boolean readyForProcessing(LIRBlock cur) {
+    private boolean readyForProcessing(LIRBlock cur) {
         // Discount the edge just traveled.
         // When the number drops to zero, all forward branches were processed
         if (decForwardBranches(cur) != 0) {
@@ -386,7 +211,7 @@
         return true;
     }
 
-    void sortIntoWorkList(LIRBlock cur) {
+    private void sortIntoWorkList(LIRBlock cur) {
         assert !workList.contains(cur) : "block already in work list";
 
         int curWeight = computeWeight(cur);
@@ -421,7 +246,7 @@
         }
     }
 
-    void appendBlock(LIRBlock cur) {
+    private void appendBlock(LIRBlock cur) {
         if (GraalOptions.TraceLinearScanLevel >= 3) {
             TTY.println("appending block B%d (weight 0x%06x) to linear-scan order", cur.blockID(), cur.linearScanNumber());
         }
@@ -434,29 +259,22 @@
         linearScanOrder.add(cur);
     }
 
-    void computeOrder(LIRBlock startBlock) {
+    private void computeOrder(LIRBlock startBlock) {
         if (GraalOptions.TraceLinearScanLevel >= 3) {
             TTY.println("----- computing final block order");
         }
 
         // the start block is always the first block in the linear scan order
         linearScanOrder = new ArrayList<LIRBlock>(numBlocks);
-//        appendBlock(startBlock);
-
-        LIRBlock stdEntry = startBlock; //.suxAt(0);
 
         // start processing with standard entry block
         assert workList.isEmpty() : "list must be empty before processing";
 
-        if (readyForProcessing(stdEntry)) {
-            sortIntoWorkList(stdEntry);
-        } else {
-            throw new CiBailout("the stdEntry must be ready for processing (otherwise, the method has no start block)");
-        }
+        assert readyForProcessing(startBlock);
+        sortIntoWorkList(startBlock);
 
         do {
             LIRBlock cur = workList.remove(workList.size() - 1);
-
             appendBlock(cur);
 
             int i;
@@ -476,9 +294,6 @@
             TTY.println("----- loop information:");
             for (LIRBlock cur : linearScanOrder) {
                 TTY.print(String.format("%4d: B%02d: ", cur.linearScanNumber(), cur.blockID()));
-                for (int loopIdx = 0; loopIdx < numLoops; loopIdx++) {
-                    TTY.print(String.format("%d = %b ", loopIdx, isBlockInLoop(loopIdx, cur)));
-                }
                 TTY.println(String.format(" . loopIndex: %2d, loopDepth: %2d", cur.loopIndex(), cur.loopDepth()));
             }
         }
@@ -512,76 +327,4 @@
             }
         }
     }
-
-    boolean verify() {
-       /* assert linearScanOrder.size() == numBlocks : "wrong number of blocks in list";
-
-        if (GraalOptions.StressLinearScan) {
-            // blocks are scrambled when StressLinearScan is used
-            return true;
-        }
-
-        // check that all successors of a block have a higher linear-scan-number
-        // and that all predecessors of a block have a lower linear-scan-number
-        // (only backward branches of loops are ignored)
-        int i;
-        for (i = 0; i < linearScanOrder.size(); i++) {
-            BlockBegin cur = linearScanOrder.get(i);
-
-            assert cur.linearScanNumber() == i : "incorrect linearScanNumber";
-            assert cur.linearScanNumber() >= 0 && cur.linearScanNumber() == linearScanOrder.indexOf(cur) : "incorrect linearScanNumber";
-
-            for (BlockBegin sux : cur.end().successors()) {
-                assert sux.linearScanNumber() >= 0 && sux.linearScanNumber() == linearScanOrder.indexOf(sux) : "incorrect linearScanNumber";
-                if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd)) {
-                    assert cur.linearScanNumber() < sux.linearScanNumber() : "invalid order";
-                }
-                if (cur.loopDepth() == sux.loopDepth()) {
-                    assert cur.loopIndex() == sux.loopIndex() || sux.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) : "successing blocks with same loop depth must have same loop index";
-                }
-            }
-
-            for (BlockBegin pred : cur.predecessors()) {
-                assert pred.linearScanNumber() >= 0 && pred.linearScanNumber() == linearScanOrder.indexOf(pred) : "incorrect linearScanNumber";
-                if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader)) {
-                    assert cur.linearScanNumber() > pred.linearScanNumber() : "invalid order";
-                }
-                if (cur.loopDepth() == pred.loopDepth()) {
-                    assert cur.loopIndex() == pred.loopIndex() || cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) : "successing blocks with same loop depth must have same loop index";
-                }
-
-                assert cur.dominator().linearScanNumber() <= pred.linearScanNumber() : "dominator must be before predecessors";
-            }
-
-            // check dominator
-            if (i == 0) {
-                assert cur.dominator() == null : "first block has no dominator";
-            } else {
-                assert cur.dominator() != null : "all but first block must have dominator";
-            }
-            assert cur.numberOfPreds() != 1 || cur.dominator() == cur.predAt(0) || cur.isExceptionEntry() : "Single predecessor must also be dominator";
-        }
-
-        // check that all loops are continuous
-        for (int loopIdx = 0; loopIdx < numLoops; loopIdx++) {
-            int blockIdx = 0;
-            assert !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx)) : "the first block must not be present in any loop";
-
-            // skip blocks before the loop
-            while (blockIdx < numBlocks && !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx))) {
-                blockIdx++;
-            }
-            // skip blocks of loop
-            while (blockIdx < numBlocks && isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx))) {
-                blockIdx++;
-            }
-            // after the first non-loop block : there must not be another loop-block
-            while (blockIdx < numBlocks) {
-                assert !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx)) : "loop not continuous in linear-scan order";
-                blockIdx++;
-            }
-        }
-*/
-        return true;
-    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java	Wed Jul 06 16:51:01 2011 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.max.graal.compiler.ir;
 
-import com.sun.cri.bytecode.Bytecodes.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
 
@@ -173,10 +172,10 @@
                     case LE: return x <= y;
                     case GT: return x > y;
                     case GE: return x >= y;
-                    case AE: return UnsignedComparisons.aboveOrEqual(x, y);
-                    case BE: return UnsignedComparisons.belowOrEqual(x, y);
-                    case AT: return UnsignedComparisons.aboveThan(x, y);
-                    case BT: return UnsignedComparisons.belowThan(x, y);
+                    case AE: return toUnsigned(x) >= toUnsigned(y);
+                    case BE: return toUnsigned(x) <= toUnsigned(y);
+                    case AT: return toUnsigned(x) > toUnsigned(y);
+                    case BT: return toUnsigned(x) < toUnsigned(y);
                 }
                 break;
             }
@@ -204,4 +203,11 @@
         }
         return null;
     }
+
+    private long toUnsigned(int x) {
+        if (x < 0) {
+            return ((long) (x & 0x7FFFFFFF)) + ((long) Integer.MAX_VALUE) + 1;
+        }
+        return x;
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java	Wed Jul 06 16:51:01 2011 +0200
@@ -55,14 +55,6 @@
         v.visitConstant(this);
     }
 
-    @Override
-    public BooleanNode negate() {
-        if (value.kind != CiKind.Boolean) {
-            throw new IllegalStateException("boolean expected, actual: " + kind);
-        }
-        return Constant.forBoolean(!value.asBoolean(), graph());
-    }
-
     /**
      * Creates an instruction for a double constant.
      * @param d the double value for which to create the instruction
@@ -179,7 +171,7 @@
     public RiType declaredType() {
         RiRuntime runtime = compilation().runtime;
         if (kind.isPrimitive()) {
-            runtime.asRiType(kind);
+            return runtime.asRiType(kind);
         }
         return runtime.getTypeOf(asConstant());
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CreateVectorNode.java	Wed Jul 06 16:51:01 2011 +0200
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.Phi.PhiType;
+import com.oracle.max.graal.compiler.phases.LoweringPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class CreateVectorNode extends AbstractVectorNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_LENGTH = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    private boolean reversed;
+
+    public void setLength(Value length) {
+        assert length == null || length.kind == CiKind.Int;
+        inputs().set(super.inputCount() + INPUT_LENGTH, length);
+    }
+
+    public boolean reversed() {
+        return reversed;
+    }
+
+    public void setReversed(boolean r) {
+        reversed = r;
+    }
+
+    public Value length() {
+        return (Value) inputs().get(super.inputCount() + INPUT_LENGTH);
+    }
+
+    public CreateVectorNode(boolean reversed, Value length, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, null, graph);
+        setLength(length);
+        setReversed(reversed);
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> debugProperties = super.getDebugProperties();
+        debugProperties.put("reversed", reversed);
+        return debugProperties;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        } else if (clazz == LoweringOp.class) {
+            return (T) LOWERING_OP;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("vector with length ").print(length().toString());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new CreateVectorNode(reversed, null, into);
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return (i instanceof CreateVectorNode);
+    }
+
+    private LoopBegin createLoop(Map<AbstractVectorNode, Value> map) {
+        EndNode end = new EndNode(graph());
+        LoopBegin loopBegin = new LoopBegin(graph());
+        loopBegin.addEnd(end);
+        Phi loopVariable = new Phi(CiKind.Int, loopBegin, PhiType.Value, graph());
+
+        if (reversed) {
+            IntegerSub add = new IntegerSub(CiKind.Int, loopVariable, Constant.forInt(1, graph()), graph());
+            loopVariable.addInput(new IntegerSub(CiKind.Int, length(), Constant.forInt(1, graph()), graph()));
+            loopVariable.addInput(add);
+        } else {
+            IntegerAdd add = new IntegerAdd(CiKind.Int, loopVariable, Constant.forInt(1, graph()), graph());
+            loopVariable.addInput(Constant.forInt(0, graph()));
+            loopVariable.addInput(add);
+        }
+
+        LoopEnd loopEnd = new LoopEnd(graph());
+        loopEnd.setLoopBegin(loopBegin);
+        Compare condition;
+        if (reversed) {
+            condition = new Compare(loopVariable, Condition.GE, Constant.forInt(0, graph()), graph());
+        } else {
+            condition = new Compare(loopVariable, Condition.LT, length(), graph());
+        }
+        If ifNode = new If(condition, graph());
+        loopBegin.setNext(ifNode);
+        ifNode.setTrueSuccessor(loopEnd);
+        this.replaceAtPredecessors(end);
+        ifNode.setFalseSuccessor(this);
+        map.put(this, loopVariable);
+        return loopBegin;
+    }
+
+    private static final LoweringOp LOWERING_OP = new LoweringOp() {
+        @Override
+        public void lower(Node n, CiLoweringTool tool) {
+            CreateVectorNode vectorNode = (CreateVectorNode) n;
+
+            IdentityHashMap<AbstractVectorNode, Value> nodes = new IdentityHashMap<AbstractVectorNode, Value>();
+            LoopBegin begin = vectorNode.createLoop(nodes);
+            for (Node use : vectorNode.usages()) {
+                processUse(begin, use, nodes);
+            }
+        }
+
+        private void processUse(LoopBegin loop, Node use, IdentityHashMap<AbstractVectorNode, Value> nodes) {
+            AbstractVectorNode vectorNode = (AbstractVectorNode) use;
+            if (nodes.containsKey(vectorNode)) {
+                return;
+            }
+            nodes.put(vectorNode, null);
+
+            // Make sure inputs are evaluated.
+            for (Node input : use.inputs()) {
+                if (input instanceof AbstractVectorNode) {
+                    AbstractVectorNode abstractVectorNodeInput = (AbstractVectorNode) input;
+                    processUse(loop, abstractVectorNodeInput, nodes);
+                }
+            }
+
+            vectorNode.addToLoop(loop, nodes);
+
+            // Go on to usages.
+            for (Node usage : use.usages()) {
+                processUse(loop, usage, nodes);
+            }
+        }
+    };
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionDispatch.java	Wed Jul 06 16:31:18 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2009, 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.compiler.ir;
-
-import com.oracle.max.graal.compiler.debug.*;
-import com.oracle.max.graal.graph.*;
-import com.sun.cri.ci.*;
-import com.sun.cri.ri.*;
-
-/**
- * This instruction takes an exception object and has two successors:
- * The catchSuccessor is called whenever the exception matches the given type, otherwise otherSuccessor is called.
- */
-public final class ExceptionDispatch extends ControlSplit {
-
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_EXCEPTION = 0;
-
-    private static final int SUCCESSOR_COUNT = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
-
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The instruction producing the exception object.
-     */
-     public Value exception() {
-        return (Value) inputs().get(super.inputCount() + INPUT_EXCEPTION);
-    }
-
-    public Value setException(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n);
-    }
-
-    private final RiType catchType;
-
-    /**
-     * Constructs a new ExceptionDispatch instruction.
-     */
-    public ExceptionDispatch(Value exception, FixedNode catchSuccessor, FixedNode otherSuccessor, RiType catchType, Graph graph) {
-        super(CiKind.Int, 2, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        setException(exception);
-        setBlockSuccessor(0, otherSuccessor);
-        setBlockSuccessor(1, catchSuccessor);
-        this.catchType = catchType;
-    }
-
-    public RiType catchType() {
-        return catchType;
-    }
-
-    /**
-     * Gets the block corresponding to the catch block.
-     * @return the true successor
-     */
-    public FixedNode catchSuccessor() {
-        return blockSuccessor(1);
-    }
-
-    /**
-     * Gets the block corresponding to the rest of the dispatch chain.
-     * @return the false successor
-     */
-    public FixedNode otherSuccessor() {
-        return blockSuccessor(0);
-    }
-
-    /**
-     * Gets the block corresponding to the specified outcome of the branch.
-     * @param istrue {@code true} if the true successor is requested, {@code false} otherwise
-     * @return the corresponding successor
-     */
-    public FixedNode successor(boolean istrue) {
-        return blockSuccessor(istrue ? 1 : 0);
-    }
-
-    @Override
-    public void accept(ValueVisitor v) {
-        v.visitExceptionDispatch(this);
-    }
-
-    @Override
-    public void print(LogStream out) {
-        out.print("exception_dispatch ").
-        print(exception()).
-        print(' ').
-        print("instanceof").
-        print(' ').
-        print(catchType().name()).
-        print(" then ").
-        print(catchSuccessor().toString()).
-        print(" else B").
-        print(otherSuccessor().toString());
-    }
-
-    @Override
-    public String shortName() {
-        return "Dispatch " + catchType().name();
-    }
-
-    @Override
-    public Node copy(Graph into) {
-        ExceptionDispatch x = new ExceptionDispatch(null, null, null, catchType, into);
-        return x;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java	Wed Jul 06 16:51:01 2011 +0200
@@ -31,25 +31,16 @@
 
 
 public final class FixedGuard extends FixedNodeWithNext {
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_NODE = 0;
-
+    private static final int INPUT_COUNT = 0;
     private static final int SUCCESSOR_COUNT = 0;
 
-    /**
-     * The instruction that produces the object tested against null.
-     */
-     public BooleanNode node() {
-        return (BooleanNode) inputs().get(super.inputCount() + INPUT_NODE);
+    public FixedGuard(BooleanNode node, Graph graph) {
+        this(graph);
+        addNode(node);
     }
 
-    public void setNode(BooleanNode n) {
-        inputs().set(super.inputCount() + INPUT_NODE, n);
-    }
-
-    public FixedGuard(BooleanNode node, Graph graph) {
+    public FixedGuard(Graph graph) {
         super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        setNode(node);
     }
 
     @Override
@@ -59,12 +50,16 @@
 
     @Override
     public void print(LogStream out) {
-        out.print("clip node ").print(node());
+        out.print("clip node ").print(inputs().toString());
+    }
+
+    public void addNode(BooleanNode node) {
+        inputs().add(node);
     }
 
     @Override
     public Node copy(Graph into) {
-        return new FixedGuard(null, into);
+        return new FixedGuard(into);
     }
 
     @SuppressWarnings("unchecked")
@@ -80,20 +75,26 @@
         @Override
         public Node canonical(Node node) {
             FixedGuard fixedGuard = (FixedGuard) node;
-            if (fixedGuard.node() instanceof Constant) {
-                Constant c = (Constant) fixedGuard.node();
-                if (c.asConstant().asBoolean()) {
-                    if (GraalOptions.TraceCanonicalizer) {
-                        TTY.println("Removing redundant fixed guard " + fixedGuard);
+            for (Node n : fixedGuard.inputs()) {
+                if (n instanceof Constant) {
+                    Constant c = (Constant) n;
+                    if (c.asConstant().asBoolean()) {
+                        if (GraalOptions.TraceCanonicalizer) {
+                            TTY.println("Removing redundant fixed guard " + fixedGuard);
+                        }
+                        fixedGuard.inputs().remove(c);
+                    } else {
+                        if (GraalOptions.TraceCanonicalizer) {
+                            TTY.println("Replacing fixed guard " + fixedGuard + " with deoptimization node");
+                        }
+                        return new Deoptimize(DeoptAction.InvalidateRecompile, fixedGuard.graph());
                     }
-                    return fixedGuard.next();
-                } else {
-                    if (GraalOptions.TraceCanonicalizer) {
-                        TTY.println("Replacing fixed guard " + fixedGuard + " with deoptimization node");
-                    }
-                    return new Deoptimize(DeoptAction.InvalidateRecompile, fixedGuard.graph());
                 }
             }
+
+            if (fixedGuard.inputs().size() == 0) {
+                return fixedGuard.next();
+            }
             return fixedGuard;
         }
     };
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java	Wed Jul 06 16:51:01 2011 +0200
@@ -55,8 +55,9 @@
         inputs().set(super.inputCount() + INPUT_NODE, n);
     }
 
-    public GuardNode(Graph graph) {
+    public GuardNode(BooleanNode node, Graph graph) {
         super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setNode(node);
     }
 
     @Override
@@ -71,7 +72,7 @@
 
     @Override
     public Node copy(Graph into) {
-        return new GuardNode(into);
+        return new GuardNode(null, into);
     }
 
     @SuppressWarnings("unchecked")
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Wed Jul 06 16:51:01 2011 +0200
@@ -81,6 +81,16 @@
         return blockSuccessor(1);
     }
 
+
+    public void setTrueSuccessor(FixedNode node) {
+        setBlockSuccessor(0, node);
+    }
+
+
+    public void setFalseSuccessor(FixedNode node) {
+        setBlockSuccessor(1, node);
+    }
+
     /**
      * Gets the block corresponding to the specified outcome of the branch.
      * @param istrue {@code true} if the true successor is requested, {@code false} otherwise
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java	Wed Jul 06 16:51:01 2011 +0200
@@ -38,13 +38,15 @@
     private static final int INPUT_COUNT = 0;
     private static final int SUCCESSOR_COUNT = 0;
 
+    private boolean nullIsTrue;
+
     /**
      * Constructs a new InstanceOf instruction.
      * @param targetClass the target class of the instanceof check
      * @param object the instruction producing the object input to this instruction
      * @param graph
      */
-    public InstanceOf(Constant targetClassInstruction, Value object, Graph graph) {
+    public InstanceOf(Constant targetClassInstruction, Value object, boolean nullIsTrue, Graph graph) {
         super(targetClassInstruction, object, CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
@@ -68,13 +70,8 @@
     }
 
     @Override
-    public BooleanNode negate() {
-        return new NotInstanceOf(targetClassInstruction(), object(), graph());
-    }
-
-    @Override
     public Node copy(Graph into) {
-        return new InstanceOf(null, null, into);
+        return new InstanceOf(null, null, nullIsTrue, into);
     }
 
     @SuppressWarnings("unchecked")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAddVectorNode.java	Wed Jul 06 16:51:01 2011 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class IntegerAddVectorNode extends AbstractVectorNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VALUE = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_VALUE);
+    }
+
+    public void setValue(Value v) {
+        inputs().set(super.inputCount() + INPUT_VALUE, v);
+    }
+
+    public IntegerAddVectorNode(AbstractVectorNode vector, Value value, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, vector, graph);
+        setValue(value);
+    }
+
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new IntegerAddVectorNode(null, null, into);
+    }
+
+    @Override
+    public void addToLoop(LoopBegin loop, IdentityHashMap<AbstractVectorNode, Value> nodes) {
+        nodes.put(this, new IntegerAdd(CiKind.Int, nodes.get(vector()), value(), graph()));
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java	Wed Jul 06 16:51:01 2011 +0200
@@ -51,21 +51,24 @@
         return super.successorCount() + SUCCESSOR_COUNT;
     }
 
-    /**
-     * The list of instructions that produce input for this instruction.
-     */
-    public Value argument(int index) {
-        assert index >= 0 && index < argumentCount;
-        return (Value) inputs().get(super.inputCount() + index);
-    }
+    public List<Value> arguments() {
+        return new AbstractList<Value>() {
+            @Override
+            public int size() {
+                return argumentCount;
+            }
 
-    public Value setArgument(int index, Value n) {
-        assert index >= 0 && index < argumentCount;
-        return (Value) inputs().set(super.inputCount() + index, n);
-    }
+            @Override
+            public Value get(int index) {
+                return (Value) inputs().get(Invoke.super.inputCount() + index);
+            }
 
-    public int argumentCount() {
-        return argumentCount;
+            @Override
+            public Value set(int index, Value node) {
+                return (Value) inputs().set(Invoke.super.inputCount() + index, node);
+            }
+        };
+
     }
 
     /**
@@ -103,7 +106,7 @@
 
         this.argumentCount = args.length;
         for (int i = 0; i < args.length; i++) {
-            setArgument(i, args[i]);
+            arguments().set(i, args[i]);
         }
     }
 
@@ -135,7 +138,7 @@
      */
     public Value receiver() {
         assert !isStatic();
-        return argument(0);
+        return arguments().get(0);
     }
 
     /**
@@ -179,7 +182,7 @@
             if (i > argStart) {
                 out.print(", ");
             }
-            out.print(argument(i));
+            out.print(arguments().get(i));
         }
         out.print(CiUtil.format(") [method: %H.%n(%p):%r]", target, false));
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadField.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadField.java	Wed Jul 06 16:51:01 2011 +0200
@@ -23,7 +23,6 @@
 package com.oracle.max.graal.compiler.ir;
 
 import com.oracle.max.graal.compiler.debug.*;
-import com.oracle.max.graal.compiler.graph.*;
 import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
 import com.oracle.max.graal.compiler.phases.*;
 import com.oracle.max.graal.compiler.phases.LoweringPhase.LoweringOp;
@@ -130,13 +129,9 @@
             LoadField loadField = (LoadField) node;
             Graph graph = node.graph();
             CiConstant constant = null;
-            if (graph instanceof CompilerGraph) {
-                RiMethod method = ((CompilerGraph) graph).getCompilation().method;
-                if (loadField.isStatic() && !method.isClassInitializer()) {
+            if (loadField.isStatic()) {
                     constant = loadField.field().constantValue(null);
-                }
-            }
-            if (!loadField.isStatic()) {
+            } else {
                 Value object = loadField.object();
                 if (object.isConstant()) {
                     constant = loadField.field().constantValue(object.asConstant());
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadIndexed.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadIndexed.java	Wed Jul 06 16:51:01 2011 +0200
@@ -23,6 +23,8 @@
 package com.oracle.max.graal.compiler.ir;
 
 import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.phases.LoweringPhase.LoweringOp;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
@@ -85,6 +87,16 @@
         return false;
     }
 
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LoweringOp.class) {
+            return (T) LoweringPhase.DELEGATE_TO_RUNTIME;
+        }
+        return super.lookup(clazz);
+    }
+
     @Override
     public Node copy(Graph into) {
         LoadIndexed x = new LoadIndexed(null, null, null, elementKind(), into);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Local.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Local.java	Wed Jul 06 16:51:01 2011 +0200
@@ -64,10 +64,10 @@
     private final int index;
     private RiType declaredType;
 
-    public Local(CiKind kind, int javaIndex, StartNode start, Graph graph) {
+    public Local(CiKind kind, int javaIndex, Graph graph) {
         super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.index = javaIndex;
-        setStart(start);
+        setStart(graph.start());
     }
 
     /**
@@ -114,7 +114,7 @@
 
     @Override
     public Node copy(Graph into) {
-        Local x = new Local(kind, index, null, into);
+        Local x = new Local(kind, index, into);
         x.setDeclaredType(declaredType());
         return x;
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java	Wed Jul 06 16:51:01 2011 +0200
@@ -26,16 +26,36 @@
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiAddress.*;
 
 
 public final class LocationNode extends FloatingNode {
-    private static final int INPUT_COUNT = 0;
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_INDEX = 0;
     private static final int SUCCESSOR_COUNT = 0;
 
+    public static final Object FINAL_LOCATION = new Object();
+
+    public static Object getArrayLocation(CiKind elementKind) {
+        return elementKind;
+    }
+
     private int displacement;
     private CiKind valueKind;
     private Object locationIdentity;
 
+    public int displacement() {
+        return displacement;
+    }
+
+    public Value index() {
+        return (Value) inputs().get(super.inputCount() + INPUT_INDEX);
+    }
+
+    public void setIndex(Value index) {
+        inputs().set(super.inputCount() + INPUT_INDEX, index);
+    }
+
     public static LocationNode create(Object identity, CiKind kind, int displacement, Graph graph) {
         LocationNode result = new LocationNode(identity, kind, displacement, graph);
         return graph.ideal(result);
@@ -71,7 +91,13 @@
     }
 
     public CiValue createAddress(LIRGenerator lirGenerator, Value object) {
-        return new CiAddress(valueKind, lirGenerator.load(object), displacement);
+        CiValue indexValue = CiValue.IllegalValue;
+        Scale indexScale = Scale.Times1;
+        if (this.index() != null) {
+            indexValue = lirGenerator.load(this.index());
+            indexScale = Scale.fromInt(valueKind.sizeInBytes(lirGenerator.target().wordSize));
+        }
+        return new CiAddress(valueKind, lirGenerator.load(object), indexValue, indexScale, displacement);
     }
 
     public Object locationIdentity() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NegateBooleanNode.java	Wed Jul 06 16:51:01 2011 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2009, 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.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code ArrayLength} instruction gets the length of an array.
+ */
+public final class NegateBooleanNode extends BooleanNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_NODE = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the array object.
+     */
+     public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_NODE);
+    }
+
+    public Value setValue(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_NODE, n);
+    }
+
+    /**
+     * Constructs a new ArrayLength instruction.
+     * @param array the instruction producing the array
+     * @param newFrameState the state after executing this instruction
+     */
+    public NegateBooleanNode(Value value, Graph graph) {
+        super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setValue(value);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof NegateBooleanNode;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print(value()).print("!");
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new NegateBooleanNode(null, into);
+    }
+
+    @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 final CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
+        @Override
+        public Node canonical(Node node) {
+            NegateBooleanNode negateNode = (NegateBooleanNode) node;
+            Value value = negateNode.value();
+            if (value instanceof NegateBooleanNode) {
+                return ((NegateBooleanNode) value).value();
+            } else if (value instanceof Constant) {
+                return Constant.forBoolean(!value.asConstant().asBoolean(), node.graph());
+            }
+            return negateNode;
+        }
+    };
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NotInstanceOf.java	Wed Jul 06 16:31:18 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2009, 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.compiler.ir;
-
-import com.oracle.max.graal.compiler.debug.*;
-import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp;
-import com.oracle.max.graal.compiler.util.*;
-import com.oracle.max.graal.graph.*;
-import com.sun.cri.bytecode.*;
-import com.sun.cri.ci.*;
-import com.sun.cri.ri.*;
-
-/**
- * The {@code InstanceOf} instruction represents an instanceof test.
- */
-public final class NotInstanceOf extends TypeCheck {
-
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
-    /**
-     * Constructs a new InstanceOf instruction.
-     * @param targetClass the target class of the instanceof check
-     * @param object the instruction producing the object input to this instruction
-     * @param graph
-     */
-    public NotInstanceOf(Constant targetClassInstruction, Value object, Graph graph) {
-        super(targetClassInstruction, object, CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-    }
-
-    @Override
-    public void accept(ValueVisitor v) {
-    }
-
-    @Override
-    public int valueNumber() {
-        return Util.hash1(Bytecodes.INSTANCEOF, object());
-    }
-
-    @Override
-    public boolean valueEqual(Node i) {
-        return i instanceof NotInstanceOf;
-    }
-
-    @Override
-    public void print(LogStream out) {
-        out.print("instanceof(").print(object()).print(") ").print(CiUtil.toJavaName(targetClass()));
-    }
-
-    @Override
-    public BooleanNode negate() {
-        return new InstanceOf(targetClassInstruction(), object(), graph());
-    }
-
-    @Override
-    public Node copy(Graph into) {
-        return new NotInstanceOf(null, null, into);
-    }
-
-    @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 CanonicalizerOp CANONICALIZER = new CanonicalizerOp() {
-        @Override
-        public Node canonical(Node node) {
-            NotInstanceOf notIsInstance = (NotInstanceOf) node;
-            Value object = notIsInstance.object();
-            RiType exactType = object.exactType();
-            if (exactType != null) {
-                return Constant.forBoolean(!exactType.isSubtypeOf(notIsInstance.targetClass()), node.graph());
-            }
-            CiConstant constant = object.asConstant();
-            if (constant != null) {
-                assert constant.kind == CiKind.Object;
-                if (constant.isNull()) {
-                    return Constant.forBoolean(true, node.graph());
-                } else {
-                    // this should never happen - non-null constants are always expected to provide an exactType
-                    assert false;
-                }
-            }
-            return notIsInstance;
-        }
-    };
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ReadVectorNode.java	Wed Jul 06 16:51:01 2011 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class ReadVectorNode extends AccessVectorNode {
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public ReadVectorNode(AbstractVectorNode vector, Value object, LocationNode location, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, vector, object, location, graph);
+    }
+
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new ReadVectorNode(null, null, null, into);
+    }
+
+
+    @Override
+    public void addToLoop(LoopBegin loop, IdentityHashMap<AbstractVectorNode, Value> nodes) {
+        LocationNode newLocation = LocationNode.create(LocationNode.getArrayLocation(location().getValueKind()), location().getValueKind(), location().displacement(), graph());
+        Value index = nodes.get(vector());
+        assert index != null;
+        newLocation.setIndex(index);
+        ReadNode readNode = new ReadNode(location().getValueKind().stackKind(), object(), newLocation, graph());
+        loop.loopEnd().replaceAtPredecessors(readNode);
+        readNode.setNext(loop.loopEnd());
+        nodes.put(this, readNode);
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java	Wed Jul 06 16:51:01 2011 +0200
@@ -93,7 +93,6 @@
                 exactType = declaredType.exactType();
             }
 
-            GraalCompilation compilation = ((CompilerGraph) node.graph()).getCompilation();
             boolean needsCheck = true;
             if (exactType != null) {
                 // we have an exact type
@@ -101,7 +100,7 @@
             } else {
                 // if either the declared type of receiver or the holder can be assumed to have no finalizers
                 if (declaredType != null && !declaredType.hasFinalizableSubclass()) {
-                    if (compilation.recordNoFinalizableSubclassAssumption(declaredType)) {
+                    if (((CompilerGraph) node.graph()).assumptions().recordNoFinalizableSubclassAssumption(declaredType)) {
                         needsCheck = false;
                     }
                 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java	Wed Jul 06 16:51:01 2011 +0200
@@ -56,8 +56,8 @@
         return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_AFTER);
     }
 
-    public FrameState setStateAfter(FrameState n) {
-        return (FrameState) inputs().set(super.inputCount() + INPUT_STATE_AFTER, n);
+    public void setStateAfter(FrameState n) {
+        inputs().set(super.inputCount() + INPUT_STATE_AFTER, n);
     }
 
     /**
@@ -76,6 +76,17 @@
     }
 
     @Override
+    public void delete() {
+        FrameState stateAfter = stateAfter();
+        super.delete();
+        if (stateAfter != null) {
+            if (stateAfter.usages().isEmpty()) {
+                stateAfter.delete();
+            }
+        }
+    }
+
+    @Override
     public Iterable< ? extends Node> dataInputs() {
         final Iterator< ? extends Node> dataInputs = super.dataInputs().iterator();
         return new Iterable<Node>() {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreIndexed.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreIndexed.java	Wed Jul 06 16:51:01 2011 +0200
@@ -23,6 +23,8 @@
 package com.oracle.max.graal.compiler.ir;
 
 import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.phases.LoweringPhase.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 
@@ -82,6 +84,15 @@
         out.print(array()).print('[').print(index()).print("] := ").print(value()).print(" (").print(kind.typeChar).print(')');
     }
 
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LoweringOp.class) {
+            return (T) LoweringPhase.DELEGATE_TO_RUNTIME;
+        }
+        return super.lookup(clazz);
+    }
+
     @Override
     public Node copy(Graph into) {
         StoreIndexed x = new StoreIndexed(null, null, null, elementKind(), null, into);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TypeCheck.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TypeCheck.java	Wed Jul 06 16:51:01 2011 +0200
@@ -61,11 +61,11 @@
     /**
      * The instruction that loads the target class object that is used by this checkcast.
      */
-     public Constant targetClassInstruction() {
-        return (Constant) inputs().get(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION);
+     public Value targetClassInstruction() {
+        return (Value) inputs().get(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION);
     }
 
-    private void setTargetClassInstruction(Constant n) {
+    private void setTargetClassInstruction(Value n) {
         inputs().set(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION, n);
     }
 
@@ -75,7 +75,7 @@
      * @return the target class
      */
     public RiType targetClass() {
-        return (RiType) targetClassInstruction().asConstant().asObject();
+        return targetClassInstruction() instanceof Constant ? (RiType) targetClassInstruction().asConstant().asObject() : null;
     }
 
     /**
@@ -87,7 +87,7 @@
      * @param successorCount
      * @param graph
      */
-    public TypeCheck(Constant targetClassInstruction, Value object, CiKind kind, int inputCount, int successorCount, Graph graph) {
+    public TypeCheck(Value targetClassInstruction, Value object, CiKind kind, int inputCount, int successorCount, Graph graph) {
         super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
         setObject(object);
         setTargetClassInstruction(targetClassInstruction);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Wed Jul 06 16:51:01 2011 +0200
@@ -53,7 +53,7 @@
      */
     public Value(CiKind kind, int inputCount, int successorCount, Graph graph) {
         super(inputCount, successorCount, graph);
-        assert kind == kind.stackKind() : kind + " != " + kind.stackKind();
+        assert kind != null && kind == kind.stackKind() : kind + " != " + kind.stackKind();
         this.kind = kind;
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java	Wed Jul 06 16:51:01 2011 +0200
@@ -69,7 +69,6 @@
     public abstract void visitStoreIndexed(StoreIndexed i);
     public abstract void visitTableSwitch(TableSwitch i);
     public abstract void visitDeoptimize(Deoptimize deoptimize);
-    public abstract void visitExceptionDispatch(ExceptionDispatch exceptionDispatch);
     public abstract void visitUnwind(Unwind unwind);
     public abstract void visitLoopBegin(LoopBegin loopBegin);
     public abstract void visitLoopEnd(LoopEnd loopEnd);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteVectorNode.java	Wed Jul 06 16:51:01 2011 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class WriteVectorNode extends AccessVectorNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VALUES = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public void setValues(AbstractVectorNode length) {
+        inputs().set(super.inputCount() + INPUT_VALUES, length);
+    }
+
+    public AbstractVectorNode values() {
+        return (AbstractVectorNode) inputs().get(super.inputCount() + INPUT_VALUES);
+    }
+
+    public WriteVectorNode(AbstractVectorNode vector, Value object, LocationNode location, AbstractVectorNode values, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, vector, object, location, graph);
+        setValues(values);
+    }
+
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("write vector node " + values());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new WriteVectorNode(null, null, null, null, into);
+    }
+
+
+    @Override
+    public void addToLoop(LoopBegin loop, IdentityHashMap<AbstractVectorNode, Value> nodes) {
+        LocationNode newLocation = LocationNode.create(LocationNode.getArrayLocation(location().getValueKind()), location().getValueKind(), location().displacement(), graph());
+        Value index = nodes.get(vector());
+        Value value = nodes.get(values());
+        assert index != null;
+        assert value != null;
+        newLocation.setIndex(index);
+        WriteNode writeNode = new WriteNode(location().getValueKind().stackKind(), object(), value, newLocation, graph());
+        loop.loopEnd().replaceAtPredecessors(writeNode);
+        writeNode.setNext(loop.loopEnd());
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java	Wed Jul 06 16:51:01 2011 +0200
@@ -27,6 +27,7 @@
 import com.oracle.max.asm.*;
 import com.oracle.max.graal.compiler.alloc.*;
 import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
@@ -174,8 +175,7 @@
     }
 
     public int loopDepth() {
-        // TODO(tw): Set correct loop depth.
-        return 0;
+        return loopDepth;
     }
 
     public int loopIndex() {
@@ -284,4 +284,8 @@
         LIROpcode code = lirInstruction.code;
         return code == LIROpcode.Branch || code == LIROpcode.TableSwitch;
     }
+
+    public boolean isExceptionEntry() {
+        return firstInstruction() instanceof ExceptionObject;
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Wed Jul 06 16:51:01 2011 +0200
@@ -73,6 +73,12 @@
                     flood.add(successor);
                 }
             }
+
+            if (current instanceof AbstractVectorNode) {
+                for (Node usage : current.usages()) {
+                    flood.add(usage);
+        }
+    }
         }
     }
 
@@ -147,17 +153,6 @@
         }
         for (Node node : graph.getNodes()) {
             if (!flood.isMarked(node)) {
-                if (node.predecessors().size() > 0) {
-                    for (Node pred : node.predecessors()) {
-                        TTY.println("!PRED! " + pred + " (" + flood.isMarked(pred) + ")");
-                        for (int i = 0; i < pred.successors().size(); i++) {
-                            TTY.println("pred=>succ: " + pred.successors().get(i));
-                        }
-                        for (int i = 0; i < pred.usages().size(); i++) {
-                            TTY.println("pred=>usage: " + pred.usages().get(i));
-                        }
-                    }
-                }
                 node.delete();
             }
         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DuplicationPhase.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DuplicationPhase.java	Wed Jul 06 16:51:01 2011 +0200
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.graph.*;
 import com.oracle.max.graal.graph.*;
 
@@ -36,13 +35,8 @@
     @Override
     protected void run(Graph graph) {
 
-        GraalCompilation compilation = null;
-        if (graph instanceof CompilerGraph) {
-            compilation = ((CompilerGraph) graph).getCompilation();
-        }
-
         // Create duplicate graph.
-        CompilerGraph duplicate = new CompilerGraph(compilation);
+        CompilerGraph duplicate = new CompilerGraph(((CompilerGraph) graph).runtime());
         Map<Node, Node> replacements = new HashMap<Node, Node>();
         replacements.put(graph.start(), duplicate.start());
         duplicate.addDuplicate(graph.getNodes(), replacements);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Wed Jul 06 16:51:01 2011 +0200
@@ -106,8 +106,6 @@
     private final Set<Block> blocksOnWorklist = new HashSet<Block>();
     private final Set<Block> blocksVisited = new HashSet<Block>();
 
-    private final boolean createUnwind;
-
     public static final Map<RiMethod, CompilerGraph> cachedGraphs = new WeakHashMap<RiMethod, CompilerGraph>();
 
     /**
@@ -117,10 +115,12 @@
      * @param ir the IR to build the graph into
      * @param graph
      */
-    public GraphBuilderPhase(GraalCompilation compilation, RiMethod method, boolean createUnwind, boolean inline) {
+    public GraphBuilderPhase(GraalCompilation compilation, RiMethod method, boolean inline) {
         super(inline ? "BuildInlineGraph" : "BuildGraph");
         this.compilation = compilation;
 
+        setDetailedName(getName() + " " + method.holder().name() + "." + method.name() + method.signature().asString());
+
         this.runtime = compilation.runtime;
         this.method = method;
         this.stats = compilation.stats;
@@ -128,7 +128,6 @@
         this.stream = new BytecodeStream(method.code());
 
         this.constantPool = runtime.getConstantPool(method);
-        this.createUnwind = createUnwind;
         this.storeResultGraph = GraalOptions.CacheGraphs;
     }
 
@@ -172,25 +171,17 @@
         Block startBlock = nextBlock(FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI);
         markOnWorkList(startBlock);
         lastInstr = (FixedNodeWithNext) createTarget(startBlock, frameState);
-        graph.start().setStart(lastInstr);
+        graph.start().setNext(lastInstr);
 
         if (isSynchronized(method.accessFlags())) {
             // 4A.1 add a monitor enter to the start block
             methodSynchronizedObject = synchronizedObject(frameState, method);
             genMonitorEnter(methodSynchronizedObject, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI);
-            // 4A.2 finish the start block
-            finishStartBlock(startBlock);
+        }
 
-            // 4A.3 setup an exception handler to unlock the root method synchronized object
-            unwindHandler = new CiExceptionHandler(0, method.code().length, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI, 0, null);
-        } else {
-            // 4B.1 simply finish the start block
-            finishStartBlock(startBlock);
-
-            if (createUnwind) {
-                unwindHandler = new CiExceptionHandler(0, method.code().length, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI, 0, null);
-            }
-        }
+        // 4B.1 simply finish the start block
+        finishStartBlock(startBlock);
+        unwindHandler = new CiExceptionHandler(0, method.code().length, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI, 0, null);
 
         // 5. SKIPPED: look for intrinsics
 
@@ -732,21 +723,22 @@
         if (entry != null) {
             append(entry);
         } else {
-            frameState.clearStack();
-            frameState.apush(exception);
-            appendGoto(createTarget(unwindBlock(bci), frameState));
+            appendGoto(createTarget(unwindBlock(bci), frameState.duplicateWithException(bci, exception)));
         }
     }
 
     private void genCheckCast() {
         int cpi = stream().readCPI();
         RiType type = constantPool.lookupType(cpi, CHECKCAST);
-        boolean isInitialized = type.isResolved();
-        Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi);
+        Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, type.isResolved());
         Value object = frameState.apop();
         if (typeInstruction != null) {
-//            append(new FixedGuard(new InstanceOf(typeInstruction, object, graph), graph));
-//            frameState.apush(object);
+//            InstanceOf instanceOf = new InstanceOf(typeInstruction, object, true, graph);
+//            FixedGuard fixedGuard = new FixedGuard(instanceOf, graph);
+//            append(fixedGuard);
+//            CastNode castNode = new CastNode(object.kind, object, graph);
+//            castNode.inputs().add(fixedGuard);
+//            frameState.apush(castNode);
             frameState.apush(new CheckCast(typeInstruction, object, graph));
         } else {
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
@@ -756,11 +748,10 @@
     private void genInstanceOf() {
         int cpi = stream().readCPI();
         RiType type = constantPool.lookupType(cpi, INSTANCEOF);
-        boolean isInitialized = type.isResolved();
-        Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi);
+        Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, type.isResolved());
         Value object = frameState.apop();
         if (typeInstruction != null) {
-            frameState.ipush(append(new MaterializeNode(new InstanceOf(typeInstruction, object, graph), graph)));
+            frameState.ipush(append(new MaterializeNode(new InstanceOf(typeInstruction, object, false, graph), graph)));
         } else {
             frameState.ipush(appendConstant(CiConstant.INT_0));
         }
@@ -851,7 +842,7 @@
         if (constantValue != null) {
             frameState.push(constantValue.kind.stackKind(), appendConstant(constantValue));
         } else {
-            Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized, cpi);
+            Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized);
             CiKind kind = field.kind();
             if (container != null) {
                 LoadField load = new LoadField(container, field, graph);
@@ -865,7 +856,7 @@
 
     private void genPutStatic(int cpi, RiField field) {
         RiType holder = field.holder();
-        Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, field.isResolved() && field.holder().isInitialized(), cpi);
+        Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, field.isResolved() && field.holder().isInitialized());
         Value value = frameState.pop(field.kind().stackKind());
         if (container != null) {
             StoreField store = new StoreField(container, field, value, graph);
@@ -875,7 +866,7 @@
         }
     }
 
-    private Constant genTypeOrDeopt(RiType.Representation representation, RiType holder, boolean initialized, int cpi) {
+    private Constant genTypeOrDeopt(RiType.Representation representation, RiType holder, boolean initialized) {
         if (initialized) {
             return appendConstant(holder.getEncoding(representation));
         } else {
@@ -902,7 +893,7 @@
             // Re-use the same resolution code as for accessing a static field. Even though
             // the result of resolution is not used by the invocation (only the side effect
             // of initialization is required), it can be commoned with static field accesses.
-            genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized, cpi);
+            genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized);
         }
         Value[] args = frameState.popArguments(target.signature().argumentSlots(false));
         appendInvoke(INVOKESTATIC, target, args, cpi, constantPool);
@@ -972,6 +963,9 @@
             Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), graph);
             Value result = appendWithBCI(invoke);
             invoke.setExceptionEdge(handleException(null, bci()));
+            if (invoke.exceptionEdge() == null) {
+                TTY.println("no exception edge" + unwindHandler);
+            }
             frameState.pushReturn(resultType, result);
         }
     }
@@ -1334,14 +1328,18 @@
             assert frameState.stackSize() == 1 : frameState;
 
             Block nextBlock = block.next == null ? unwindBlock(block.deoptBci) : block.next;
-            if (block.handler.catchType().isResolved()) {
+
+
+            RiType catchType = block.handler.catchType();
+            Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, catchType, catchType.isResolved());
+            if (typeInstruction != null) {
                 FixedNode catchSuccessor = createTarget(blockFromBci[block.handler.handlerBCI()], frameState);
                 FixedNode nextDispatch = createTarget(nextBlock, frameState);
-                append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), graph));
-            } else {
-                Deoptimize deopt = new Deoptimize(DeoptAction.InvalidateRecompile, graph);
-                deopt.setMessage("unresolved " + block.handler.catchType().name());
-                append(deopt);
+                Value exception = frameState.stackAt(0);
+                If ifNode = new If(new InstanceOf(typeInstruction, exception, false, graph), graph);
+                append(ifNode);
+                ifNode.setTrueSuccessor(catchSuccessor);
+                ifNode.setFalseSuccessor(nextDispatch);
             }
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Wed Jul 06 16:51:01 2011 +0200
@@ -54,11 +54,11 @@
     }
 
     private Queue<Invoke> newInvokes = new ArrayDeque<Invoke>();
-    private Graph graph;
+    private CompilerGraph graph;
 
     @Override
     protected void run(Graph graph) {
-        this.graph = graph;
+        this.graph = (CompilerGraph) graph;
 
         float ratio = GraalOptions.MaximumInlineRatio;
         inliningSize = compilation.method.codeSize();
@@ -118,13 +118,13 @@
     private RiMethod inlineInvoke(Invoke invoke, int iterations, float ratio) {
         RiMethod parent = invoke.stateAfter().method();
         RiTypeProfile profile = parent.typeProfile(invoke.bci);
+        if (GraalOptions.Intrinsify && compilation.runtime.intrinsicGraph(invoke.target, invoke.arguments()) != null) {
+            // Always intrinsify.
+            return invoke.target;
+        }
         if (!checkInvokeConditions(invoke)) {
             return null;
         }
-        if (invoke.target.hasIntrinsicGraph() && GraalOptions.Intrinsify) {
-            // Always intrinsify.
-            return invoke.target;
-        }
         if (invoke.opcode() == Bytecodes.INVOKESPECIAL || invoke.target.canBeStaticallyBound()) {
             if (checkTargetConditions(invoke.target, iterations) && checkSizeConditions(invoke.target, invoke, profile, ratio)) {
                 return invoke.target;
@@ -159,7 +159,7 @@
                     String concreteName = CiUtil.format("%H.%n(%p):%r", concrete, false);
                     TTY.println("recording concrete method assumption: %s -> %s", targetName, concreteName);
                 }
-                compilation.assumptions.recordConcreteMethod(invoke.target, concrete);
+                graph.assumptions().recordConcreteMethod(invoke.target, concrete);
                 return concrete;
             }
             return null;
@@ -323,40 +323,42 @@
             exceptionEdge = ((Placeholder) exceptionEdge).next();
         }
 
-        boolean withReceiver = !Modifier.isStatic(method.accessFlags());
+        boolean withReceiver = !invoke.isStatic();
 
         int argumentCount = method.signature().argumentCount(false);
         Value[] parameters = new Value[argumentCount + (withReceiver ? 1 : 0)];
         int slot = withReceiver ? 1 : 0;
         int param = withReceiver ? 1 : 0;
         for (int i = 0; i < argumentCount; i++) {
-            parameters[param++] = invoke.argument(slot);
+            parameters[param++] = invoke.arguments().get(slot);
             slot += method.signature().argumentKindAt(i).sizeInSlots();
         }
         if (withReceiver) {
-            parameters[0] = invoke.argument(0);
+            parameters[0] = invoke.arguments().get(0);
         }
 
         CompilerGraph graph = null;
         if (GraalOptions.Intrinsify) {
-            graph = (CompilerGraph) method.intrinsicGraph(parameters);
+            graph = (CompilerGraph) compilation.runtime.intrinsicGraph(method, invoke.arguments());
         }
         if (graph != null) {
-            TTY.println("Using intrinsic graph");
+            if (GraalOptions.TraceInlining) {
+                TTY.println("Using intrinsic graph");
+            }
         } else {
             graph = GraphBuilderPhase.cachedGraphs.get(method);
         }
 
         if (graph != null) {
             if (GraalOptions.TraceInlining) {
-                TTY.println("Reusing graph for %s, locals: %d, stack: %d", methodName(method, invoke), method.maxLocals(), method.maxStackSize());
+                TTY.println("Reusing graph for %s", methodName(method, invoke));
             }
         } else {
             if (GraalOptions.TraceInlining) {
                 TTY.println("Building graph for %s, locals: %d, stack: %d", methodName(method, invoke), method.maxLocals(), method.maxStackSize());
             }
             graph = new CompilerGraph(null);
-            new GraphBuilderPhase(compilation, method, true, true).apply(graph);
+            new GraphBuilderPhase(compilation, method, true).apply(graph);
         }
 
         invoke.inputs().clearAll();
@@ -396,14 +398,25 @@
         } else {
             pred = new Placeholder(compilation.graph);
         }
-        invoke.predecessors().get(0).successors().replace(invoke, pred);
+        invoke.replaceAtPredecessors(pred);
         replacements.put(startNode, pred);
 
         Map<Node, Node> duplicates = compilation.graph.addDuplicate(nodes, replacements);
 
+        FrameState stateBefore = null;
         for (Node node : duplicates.values()) {
             if (node instanceof Invoke) {
                 newInvokes.add((Invoke) node);
+            } else if (node instanceof FrameState) {
+                FrameState frameState = (FrameState) node;
+                if (frameState.bci == FrameState.BEFORE_BCI) {
+                    if (stateBefore == null) {
+                        stateBefore = stateAfter.duplicateModified(invoke.bci, false, invoke.kind, parameters);
+                    }
+                    frameState.replaceAndDelete(stateBefore);
+                } else if (frameState.bci == FrameState.AFTER_BCI) {
+                    frameState.replaceAndDelete(stateAfter);
+                }
             }
         }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java	Wed Jul 06 16:51:01 2011 +0200
@@ -57,11 +57,13 @@
     }
 
     private void process(final Block b) {
+
+        final Node anchor = b.javaBlock().createAnchor();
         final CiLoweringTool loweringTool = new CiLoweringTool() {
 
             @Override
             public Node getGuardAnchor() {
-                return b.createAnchor();
+                return anchor;
             }
 
             @Override
@@ -72,19 +74,13 @@
             @Override
             public Node createGuard(Node condition) {
                 Anchor anchor = (Anchor) getGuardAnchor();
-                for (GuardNode guard : anchor.happensAfterGuards()) {
-                    if (guard.node().valueEqual(condition)) {
-                        condition.delete();
-                        return guard;
-                    }
-                }
-                GuardNode newGuard = new GuardNode(anchor.graph());
+                GuardNode newGuard = new GuardNode((BooleanNode) condition, anchor.graph());
                 newGuard.setAnchor(anchor);
-                newGuard.setNode((BooleanNode) condition);
                 return newGuard;
             }
         };
 
+
         // Lower the instructions of this block.
         for (final Node n : b.getInstructions()) {
             if (n instanceof FixedNode) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java	Wed Jul 06 16:51:01 2011 +0200
@@ -72,8 +72,8 @@
             StartNode startNode = b.firstNode().graph().start();
             if (b.firstNode() == startNode) {
                 WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(startNode.graph());
-                checkpoint.setNext((FixedNode) startNode.start());
-                startNode.setStart(checkpoint);
+                checkpoint.setNext((FixedNode) startNode.next());
+                startNode.setNext(checkpoint);
                 mergeForWrite = checkpoint;
                 mergeForRead = checkpoint;
             }
@@ -315,6 +315,8 @@
             LoopBegin begin = end.loopBegin();
             Block beginBlock = nodeMap.get(begin);
             MemoryMap memoryMap = memoryMaps[beginBlock.blockID()];
+            assert memoryMap != null : beginBlock.name();
+            assert memoryMap.getLoopEntryMap() != null;
             memoryMap.getLoopEntryMap().resetMergeOperationCount();
             memoryMap.getLoopEntryMap().mergeWith(map, beginBlock);
             Node loopCheckPoint = memoryMap.getLoopCheckPoint();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java	Wed Jul 06 16:51:01 2011 +0200
@@ -30,12 +30,14 @@
 public abstract class Phase {
 
     private final String name;
+    private String detailedName;
     private static final ThreadLocal<Phase> currentPhase = new ThreadLocal<Phase>();
     private final boolean shouldVerify;
 
     public Phase() {
         this.name = this.getClass().getSimpleName();
         this.shouldVerify = true;
+        this.detailedName = name;
     }
 
     public Phase(String name) {
@@ -45,6 +47,11 @@
     public Phase(String name, boolean shouldVerify) {
         this.name = name;
         this.shouldVerify = shouldVerify;
+        this.detailedName = name;
+    }
+
+    protected void setDetailedName(String detailedName) {
+        this.detailedName = detailedName;
     }
 
     public final void apply(Graph graph) {
@@ -71,13 +78,13 @@
         } catch (AssertionError t) {
             GraalCompilation compilation = GraalCompilation.compilation();
             if (compilation.compiler.isObserved() && plotOnError) {
-                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "AssertionError in " + getName(), graph, true, false, true));
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "AssertionError in " + detailedName, graph, true, false, true));
             }
             throw t;
         } catch (RuntimeException t) {
             GraalCompilation compilation = GraalCompilation.compilation();
             if (compilation.compiler.isObserved() && plotOnError) {
-                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in " + getName(), graph, true, false, true));
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in " + detailedName, graph, true, false, true));
             }
             throw t;
         }
@@ -98,7 +105,7 @@
         }
         GraalCompilation compilation = GraalCompilation.compilation();
         if (compilation.compiler.isObserved() && this.getClass() != IdentifyBlocksPhase.class) {
-            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After " + getName(), graph, true, false));
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After " + detailedName, graph, true, false));
         }
 
         assert !shouldVerify || graph.verify();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java	Wed Jul 06 16:51:01 2011 +0200
@@ -35,14 +35,16 @@
     @Override
     protected void run(Graph graph) {
         for (ReadNode n : graph.getNodes(ReadNode.class)) {
-            Node memoryInput = n.inputs().variablePart().get(0);
-            if (memoryInput instanceof WriteNode) {
-                WriteNode other = (WriteNode) memoryInput;
-                if (other.object() == n.object() && other.location() == n.location()) {
-                    if (GraalOptions.TraceReadElimination) {
-                        TTY.println("Eliminated memory read " + n + "and replaced with node " + other.value());
+            if (n.inputs().variablePart().size() > 0) {
+                Node memoryInput = n.inputs().variablePart().get(0);
+                if (memoryInput instanceof WriteNode) {
+                    WriteNode other = (WriteNode) memoryInput;
+                    if (other.object() == n.object() && other.location() == n.location()) {
+                        if (GraalOptions.TraceReadElimination) {
+                            TTY.println("Eliminated memory read " + n + "and replaced with node " + other.value());
+                        }
+                        n.replaceAndDelete(other.value());
                     }
-                    n.replaceAndDelete(other.value());
                 }
             }
         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Wed Jul 06 16:51:01 2011 +0200
@@ -38,6 +38,8 @@
     private Block javaBlock;
     private final List<Block> dominators = new ArrayList<Block>();
     private Anchor anchor;
+    private int loopDepth = 0;
+    private int loopIndex = -1;
 
     private Node firstNode;
     private Node lastNode;
@@ -63,18 +65,34 @@
         return lastNode;
     }
 
+    public int loopDepth() {
+        return loopDepth;
+    }
+
+    public void setLoopDepth(int i) {
+        loopDepth = i;
+    }
+
+    public int loopIndex() {
+        return loopIndex;
+    }
+
+    public void setLoopIndex(int i) {
+        loopIndex = i;
+    }
+
     public Anchor createAnchor() {
         if (anchor == null) {
             if (firstNode instanceof Anchor) {
                 this.anchor = (Anchor) firstNode;
             } else if (firstNode == firstNode.graph().start()) {
                 StartNode start = (StartNode) firstNode;
-                if (start.start() instanceof Anchor) {
-                    this.anchor = (Anchor) start.start();
+                if (start.next() instanceof Anchor) {
+                    this.anchor = (Anchor) start.next();
                 } else {
                     Anchor a = new Anchor(firstNode.graph());
-                    a.setNext((FixedNode) firstNode.graph().start().start());
-                    firstNode.graph().start().setStart(a);
+                    a.setNext((FixedNode) firstNode.graph().start().next());
+                    firstNode.graph().start().setNext(a);
                     this.anchor = a;
                 }
             } else if (firstNode instanceof Merge) {
@@ -175,6 +193,10 @@
         return firstNode instanceof LoopBegin;
     }
 
+    public boolean isLoopEnd() {
+        return lastNode instanceof LoopEnd;
+    }
+
     public Block dominator() {
         return dominator;
     }
@@ -224,4 +246,8 @@
             }
         }
     }
+
+    public String name() {
+        return "B" + blockID;
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Wed Jul 06 16:51:01 2011 +0200
@@ -24,6 +24,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.oracle.max.graal.compiler.phases.*;
@@ -36,6 +37,7 @@
     private NodeMap<Block> nodeToBlock;
     private Graph graph;
     private boolean scheduleAllNodes;
+    private int loopCount;
 
     public IdentifyBlocksPhase(boolean scheduleAllNodes) {
         super(scheduleAllNodes ? "FullSchedule" : "PartSchedule", false);
@@ -64,6 +66,10 @@
         return b;
     }
 
+    public int loopCount() {
+        return loopCount;
+    }
+
     private Block assignBlockNew(Node n, Block b) {
         if (b == null) {
             b = createBlock();
@@ -71,6 +77,20 @@
 
         assert nodeToBlock.get(n) == null;
         nodeToBlock.set(n, b);
+
+        if (n instanceof Merge) {
+            for (Node usage : n.usages()) {
+
+                if (usage instanceof Phi) {
+                    nodeToBlock.set(usage, b);
+                }
+
+                if (usage instanceof LoopCounter) {
+                    nodeToBlock.set(usage, b);
+                }
+
+            }
+        }
         if (b.lastNode() == null) {
             b.setFirstNode(n);
             b.setLastNode(n);
@@ -154,17 +174,7 @@
 
 
         if (scheduleAllNodes) {
-
-            // Add successors of loop end nodes. Makes the graph cyclic.
-            for (Block block : blocks) {
-                Node n = block.lastNode();
-                if (n instanceof LoopEnd) {
-                    LoopEnd loopEnd = (LoopEnd) n;
-                    assert loopEnd.loopBegin() != null;
-                    block.addSuccessor(nodeToBlock.get(loopEnd.loopBegin()));
-                }
-            }
-
+            computeLoopInformation(); // Will make the graph cyclic.
             assignLatestPossibleBlockToNodes();
             sortNodesWithinBlocks();
         } else {
@@ -172,6 +182,47 @@
         }
     }
 
+    private void computeLoopInformation() {
+
+        // Add successors of loop end nodes. Makes the graph cyclic.
+        for (Block block : blocks) {
+            Node n = block.lastNode();
+            if (n instanceof LoopEnd) {
+                LoopEnd loopEnd = (LoopEnd) n;
+                assert loopEnd.loopBegin() != null;
+                Block loopBeginBlock = nodeToBlock.get(loopEnd.loopBegin());
+                block.addSuccessor(loopBeginBlock);
+                BitMap map = new BitMap(blocks.size());
+                markBlocks(block, loopBeginBlock, map, loopCount++, block.loopDepth());
+            }
+        }
+
+//        for (Block block : blocks) {
+//            TTY.println("Block B" + block.blockID() + " loopIndex=" + block.loopIndex() + ", loopDepth=" + block.loopDepth());
+//        }
+    }
+
+    private void markBlocks(Block block, Block endBlock, BitMap map, int loopIndex, int initialDepth) {
+        if (map.get(block.blockID())) {
+            return;
+        }
+
+        map.set(block.blockID());
+        if (block.loopDepth() <= initialDepth) {
+            assert block.loopDepth() == initialDepth;
+            block.setLoopIndex(loopIndex);
+        }
+        block.setLoopDepth(block.loopDepth() + 1);
+
+        if (block == endBlock) {
+            return;
+        }
+
+        for (Block pred : block.getPredecessors()) {
+            markBlocks(pred, endBlock, map, loopIndex, initialDepth);
+        }
+    }
+
     private void computeJavaBlocks() {
 
         for (Block b : blocks) {
@@ -240,16 +291,6 @@
 
         assert !n.isDeleted();
 
-        if (n instanceof Phi) {
-            Block block = nodeToBlock.get(((Phi) n).merge());
-            nodeToBlock.set(n, block);
-        }
-
-        if (n instanceof LoopCounter) {
-            Block block = nodeToBlock.get(((LoopCounter) n).loopBegin());
-            nodeToBlock.set(n, block);
-        }
-
         Block prevBlock = nodeToBlock.get(n);
         if (prevBlock != null) {
             return prevBlock;
@@ -294,13 +335,76 @@
             }
         }
 
-        nodeToBlock.set(n, block);
+
         if (block != null) {
+            if (GraalOptions.OptOptimisticSchedule) {
+                block = scheduleOutOfLoops(n, block);
+            }
+            nodeToBlock.set(n, block);
             block.getInstructions().add(n);
         }
         return block;
     }
 
+    private Block scheduleOutOfLoops(Node n, Block latestBlock) {
+        Block cur = latestBlock;
+        while (cur.loopDepth() != 0) {
+            if (cur.isLoopHeader()) {
+                assert cur.getPredecessors().size() == 2 : cur.getPredecessors().size();
+                if (canSchedule(n, cur.getPredecessors().get(0))) {
+                   // TTY.println("can schedule out of loop!" + n);
+                    return scheduleOutOfLoops(n, cur.getPredecessors().get(0));
+                } else {
+                    break;
+                }
+            }
+            Block prev = cur;
+            cur = cur.dominator();
+
+            // This must be a loop exit.
+            if (cur.loopDepth() > prev.loopDepth()) {
+//                TTY.println("break out because of different loop depth");
+                break;
+            }
+        }
+        return latestBlock;
+    }
+
+    private boolean canSchedule(Node n, Block block) {
+        Set<Block> allowedBlocks = new HashSet<Block>();
+        Block cur = block;
+        while (cur != null) {
+            allowedBlocks.add(cur);
+            cur = cur.dominator();
+        }
+        // Now we know the allowed blocks for inputs and predecessors.
+        return checkNodesAbove(allowedBlocks, n);
+    }
+
+    private boolean checkNodesAbove(Set<Block> allowedBlocks, Node n) {
+        if (n == null) {
+            return true;
+        }
+
+        if (nodeToBlock.get(n) != null) {
+            return allowedBlocks.contains(nodeToBlock.get(n));
+        } else {
+            assert !(n instanceof Phi) : ((Phi) n).merge();
+            for (Node input : n.inputs()) {
+                if (!checkNodesAbove(allowedBlocks, input)) {
+                    return false;
+                }
+            }
+            for (Node pred : n.predecessors()) {
+                if (!checkNodesAbove(allowedBlocks, pred)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+
     private Block getCommonDominator(Block a, Block b) {
         if (a == null) {
             return b;
@@ -323,15 +427,11 @@
         List<Node> sortedInstructions = new ArrayList<Node>(instructions.size() + 2);
 
         assert !map.isMarked(b.firstNode()) && nodeToBlock.get(b.firstNode()) == b;
-//        assert !instructions.contains(b.firstNode());
-//        assert !instructions.contains(b.lastNode());
         assert !map.isMarked(b.lastNode()) && nodeToBlock.get(b.lastNode()) == b;
 
-        //addToSorting(b, b.firstNode(), sortedInstructions, map);
         for (Node i : instructions) {
             addToSorting(b, i, sortedInstructions, map);
         }
-        //addToSorting(b, b.lastNode(), sortedInstructions, map);
 
         // Make sure that last node gets really last (i.e. when a frame state successor hangs off it).
         Node lastSorted = sortedInstructions.get(sortedInstructions.size() - 1);
@@ -366,7 +466,7 @@
         }
 
         if (i instanceof WriteNode) {
-            // Make sure every ReadNode that is connected to the same memory state is executed before every write node.
+            // TODO(tw): Make sure every ReadNode that is connected to the same memory state is executed before every write node.
             WriteNode wn = (WriteNode) i;
             // TODO: Iterate over variablePart.
             wn.inputs().variablePart();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Wed Jul 06 16:51:01 2011 +0200
@@ -554,6 +554,8 @@
                     case GT : acond = ConditionFlag.greater; break;
                     case BE : acond = ConditionFlag.belowEqual; break;
                     case AE : acond = ConditionFlag.aboveEqual; break;
+                    case AT : acond = ConditionFlag.above; break;
+                    case BT : acond = ConditionFlag.below; break;
                     default : throw Util.shouldNotReachHere();
                 }
                 // Checkstyle: on
@@ -1298,11 +1300,11 @@
                     default      : throw Util.shouldNotReachHere();
                 }
             } else {
-                throw Util.shouldNotReachHere();
+                throw Util.shouldNotReachHere("opr1=" + opr1.toString() + " opr2=" + opr2);
             }
 
         } else {
-            throw Util.shouldNotReachHere(opr1.toString() + " opr2 = " + opr2);
+            throw Util.shouldNotReachHere("opr1=" + opr1.toString() + " opr2=" + opr2);
         }
         // Checkstyle: on
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java	Wed Jul 06 16:51:01 2011 +0200
@@ -33,9 +33,6 @@
 import com.oracle.max.graal.compiler.util.*;
 import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
-import com.sun.cri.ri.*;
-import com.sun.cri.ri.RiType.*;
-import com.sun.cri.xir.*;
 
 /**
  * This class implements the X86-specific portion of the LIR generator.
@@ -466,30 +463,11 @@
     }
 
     @Override
-    public void visitExceptionDispatch(ExceptionDispatch x) {
-        // TODO ls: this needs some more work...
-
-        RiType riType = x.catchType();
-        assert riType.isResolved();
-
-        XirArgument obj = toXirArgument(x.exception());
-        XirArgument clazz = toXirArgument(riType.getEncoding(Representation.ObjectHub));
-        XirSnippet snippet = xir.genInstanceOf(site(x), obj, clazz, riType);
-        emitXir(snippet, x, stateFor(x), null, false);
-
-        LIRXirInstruction instr = (LIRXirInstruction) lir.instructionsList().get(lir.instructionsList().size() - 1);
-        instr.setTrueSuccessor(getLIRBlock(x.catchSuccessor()));
-        lir.jump(getLIRBlock(x.otherSuccessor()));
-    }
-
-    @Override
     public void visitLoopBegin(LoopBegin x) {
-
     }
 
     @Override
     public void visitValueAnchor(ValueAnchor valueAnchor) {
         // nothing to do for ValueAnchors
     }
-
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Wed Jul 06 16:51:01 2011 +0200
@@ -54,6 +54,9 @@
 
     private static final int SUCCESSOR_COUNT = 0;
 
+    public static final int BEFORE_BCI = -2;
+    public static final int AFTER_BCI = -3;
+
     @Override
     protected int inputCount() {
         return super.inputCount() + localsSize + stackSize + locksSize;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java	Wed Jul 06 16:51:01 2011 +0200
@@ -43,6 +43,7 @@
     private final ArrayList<Value> locks;
 
     private int stackIndex;
+    private boolean rethrowException;
 
     private final RiMethod method;
 
@@ -59,7 +60,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.start(), graph);
+            Local local = new Local(method.holder().kind(), javaIndex, graph);
             local.setDeclaredType(method.holder());
             storeLocal(javaIndex, local);
             javaIndex = 1;
@@ -71,7 +72,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.start(), graph);
+            Local local = new Local(kind, index, graph);
             if (type.isResolved()) {
                 local.setDeclaredType(type);
             }
@@ -102,10 +103,11 @@
         for (int i = 0; i < other.locksSize(); i++) {
             locks.add(other.lockAt(i));
         }
+        this.rethrowException = other.rethrowException();
     }
 
     public FrameState create(int bci) {
-        return new FrameState(method, bci, locals, stack, stackIndex, locks, false, graph);
+        return new FrameState(method, bci, locals, stack, stackIndex, locks, rethrowException, graph);
     }
 
     public FrameState duplicateWithException(int bci, Value exceptionObject) {
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java	Wed Jul 06 16:51:01 2011 +0200
@@ -223,14 +223,4 @@
             }
         }
     }
-
-    @Override
-    public Graph intrinsicGraph(Node[] parameters) {
-        return null;
-    }
-
-    @Override
-    public boolean hasIntrinsicGraph() {
-        return false;
-    }
 }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java	Wed Jul 06 16:51:01 2011 +0200
@@ -177,14 +177,4 @@
     public int branchProbability(int bci) {
         return -1;
     }
-
-    @Override
-    public Graph intrinsicGraph(Node[] parameters) {
-        return null;
-    }
-
-    @Override
-    public boolean hasIntrinsicGraph() {
-        return false;
-    }
 }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Wed Jul 06 16:51:01 2011 +0200
@@ -26,7 +26,10 @@
 import java.lang.reflect.*;
 import java.util.*;
 
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.graph.*;
 import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.runtime.nodes.*;
 import com.sun.cri.ci.*;
@@ -34,6 +37,7 @@
 import com.sun.cri.ci.CiTargetMethod.DataPatch;
 import com.sun.cri.ci.CiTargetMethod.Safepoint;
 import com.sun.cri.ri.*;
+import com.sun.cri.ri.RiType.Representation;
 import com.sun.max.asm.dis.*;
 import com.sun.max.lang.*;
 
@@ -46,6 +50,7 @@
     final HotSpotRegisterConfig regConfig;
     final HotSpotRegisterConfig globalStubRegConfig;
     private final Compiler compiler;
+    private IdentityHashMap<RiMethod, CompilerGraph> intrinsicGraphs = new IdentityHashMap<RiMethod, CompilerGraph>();
 
 
     public HotSpotRuntime(HotSpotVMConfig config, Compiler compiler) {
@@ -243,6 +248,10 @@
 
     @Override
     public void lower(Node n, CiLoweringTool tool) {
+        if (!GraalOptions.Lower) {
+            return;
+        }
+
         if (n instanceof LoadField) {
             LoadField field = (LoadField) n;
             if (field.isVolatile()) {
@@ -274,6 +283,217 @@
                 memoryWrite.setNext(field.next());
             }
             field.replaceAndDelete(memoryWrite);
+        } else if (n instanceof LoadIndexed) {
+            LoadIndexed loadIndexed = (LoadIndexed) n;
+            Graph graph = loadIndexed.graph();
+            GuardNode boundsCheck = createBoundsCheck(loadIndexed, tool);
+
+            CiKind elementKind = loadIndexed.elementKind();
+            LocationNode arrayLocation = createArrayLocation(graph, elementKind);
+            arrayLocation.setIndex(loadIndexed.index());
+            ReadNode memoryRead = new ReadNode(elementKind.stackKind(), loadIndexed.array(), arrayLocation, graph);
+            memoryRead.setGuard(boundsCheck);
+            memoryRead.setNext(loadIndexed.next());
+            loadIndexed.replaceAndDelete(memoryRead);
+        } else if (n instanceof StoreIndexed) {
+            StoreIndexed storeIndexed = (StoreIndexed) n;
+            Graph graph = storeIndexed.graph();
+            Anchor anchor = new Anchor(graph);
+            GuardNode boundsCheck = createBoundsCheck(storeIndexed, tool);
+            anchor.inputs().add(boundsCheck);
+
+
+            CiKind elementKind = storeIndexed.elementKind();
+            LocationNode arrayLocation = createArrayLocation(graph, elementKind);
+            arrayLocation.setIndex(storeIndexed.index());
+            Value value = storeIndexed.value();
+            if (elementKind == CiKind.Object) {
+                // Store check!
+                if (storeIndexed.array().exactType() != null) {
+                    RiType elementType = storeIndexed.array().exactType().componentType();
+                    if (elementType.superType() != null) {
+                        Constant type = new Constant(elementType.getEncoding(Representation.ObjectHub), graph);
+                        value = new CheckCast(type, value, graph);
+                    } else {
+                        assert elementType.name().equals("Ljava/lang/Object;") : elementType.name();
+                    }
+                } else {
+                    ReadNode arrayKlass = new ReadNode(CiKind.Object, storeIndexed.array(), LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), graph);
+                    ReadNode arrayElementKlass = new ReadNode(CiKind.Object, arrayKlass, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.arrayClassElementOffset, graph), graph);
+                    value = new CheckCast(arrayElementKlass, value, graph);
+                }
+            }
+            WriteNode memoryWrite = new WriteNode(elementKind.stackKind(), storeIndexed.array(), value, arrayLocation, graph);
+            memoryWrite.setGuard(boundsCheck);
+            memoryWrite.setStateAfter(storeIndexed.stateAfter());
+            anchor.setNext(memoryWrite);
+            if (elementKind == CiKind.Object && !value.isNullConstant()) {
+                ArrayWriteBarrier writeBarrier = new ArrayWriteBarrier(storeIndexed.array(), arrayLocation, graph);
+                memoryWrite.setNext(writeBarrier);
+                writeBarrier.setNext(storeIndexed.next());
+            } else {
+                memoryWrite.setNext(storeIndexed.next());
+            }
+            storeIndexed.replaceAtPredecessors(anchor);
+            storeIndexed.delete();
         }
     }
+
+    private LocationNode createArrayLocation(Graph graph, CiKind elementKind) {
+        return LocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), graph);
+    }
+
+    private GuardNode createBoundsCheck(AccessIndexed n, CiLoweringTool tool) {
+        return (GuardNode) tool.createGuard(new Compare(n.index(), Condition.BT, n.length(), n.graph()));
+    }
+
+    @Override
+    public Graph intrinsicGraph(RiMethod method, List<? extends Node> parameters) {
+        if (!intrinsicGraphs.containsKey(method)) {
+            RiType holder = method.holder();
+            String fullName = method.name() + method.signature().asString();
+            String holderName = holder.name();
+            if (holderName.equals("Ljava/lang/Object;")) {
+                if (fullName.equals("getClass()Ljava/lang/Class;")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Local receiver = new Local(CiKind.Object, 0, graph);
+                    ReadNode klassOop = new ReadNode(CiKind.Object, receiver, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), graph);
+                    Return ret = new Return(new ReadNode(CiKind.Object, klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph), graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                }
+            } else if (holderName.equals("Ljava/lang/System;")) {
+                if (fullName.equals("arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Local src = new Local(CiKind.Object, 0, graph);
+                    Local srcPos = new Local(CiKind.Int, 1, graph);
+                    Local dest = new Local(CiKind.Object, 2, graph);
+                    Local destPos = new Local(CiKind.Int, 3, graph);
+                    Value length = new Local(CiKind.Int, 4, graph);
+                    src.setDeclaredType(((Value) parameters.get(0)).declaredType());
+                    dest.setDeclaredType(((Value) parameters.get(2)).declaredType());
+
+                    if (src.declaredType() == null || dest.declaredType() == null) {
+                        return null;
+                    }
+
+                    if (src.declaredType() != dest.declaredType()) {
+                        return null;
+                    }
+
+                    if (!src.declaredType().isArrayClass()) {
+                        return null;
+                    }
+
+                    CiKind componentType = src.declaredType().componentType().kind();
+
+                    if (componentType == CiKind.Object) {
+                        return null;
+                    }
+
+                    FrameState stateBefore = new FrameState(method, FrameState.BEFORE_BCI, 0, 0, 0, false, graph);
+                    FrameState stateAfter = new FrameState(method, FrameState.AFTER_BCI, 0, 0, 0, false, graph);
+
+                    // Add preconditions.
+                    FixedGuard guard = new FixedGuard(graph);
+                    ArrayLength srcLength = new ArrayLength(src, graph);
+                    ArrayLength destLength = new ArrayLength(dest, graph);
+                    IntegerAdd upperLimitSrc = new IntegerAdd(CiKind.Int, srcPos, length, graph);
+                    IntegerAdd upperLimitDest = new IntegerAdd(CiKind.Int, destPos, length, graph);
+                    guard.addNode(new Compare(srcPos, Condition.BE, srcLength, graph));
+                    guard.addNode(new Compare(destPos, Condition.BE, destLength, graph));
+                    guard.addNode(new Compare(length, Condition.GE, Constant.forInt(0, graph), graph));
+                    guard.addNode(new Compare(upperLimitSrc, Condition.LE, srcLength, graph));
+                    guard.addNode(new Compare(upperLimitDest, Condition.LE, destLength, graph));
+                    graph.start().setNext(guard);
+
+                    LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, componentType, config.getArrayOffset(componentType), graph);
+
+                    // Build normal vector instruction.
+                    CreateVectorNode normalVector = new CreateVectorNode(false, length, graph);
+                    ReadVectorNode values = new ReadVectorNode(new IntegerAddVectorNode(normalVector, srcPos, graph), src, location, graph);
+                    new WriteVectorNode(new IntegerAddVectorNode(normalVector, destPos, graph), dest, location, values, graph);
+                    normalVector.setStateAfter(stateAfter);
+
+                    // Build reverse vector instruction.
+                    CreateVectorNode reverseVector = new CreateVectorNode(true, length, graph);
+                    ReadVectorNode reverseValues = new ReadVectorNode(new IntegerAddVectorNode(reverseVector, srcPos, graph), src, location, graph);
+                    new WriteVectorNode(new IntegerAddVectorNode(reverseVector, destPos, graph), dest, location, reverseValues, graph);
+                    reverseVector.setStateAfter(stateAfter);
+
+                    If ifNode = new If(new Compare(src, Condition.EQ, dest, graph), graph);
+                    guard.setNext(ifNode);
+
+                    If secondIf = new If(new Compare(srcPos, Condition.LT, destPos, graph), graph);
+                    ifNode.setTrueSuccessor(secondIf);
+
+                    secondIf.setTrueSuccessor(reverseVector);
+
+                    Merge merge1 = new Merge(graph);
+                    merge1.addEnd(new EndNode(graph));
+                    merge1.addEnd(new EndNode(graph));
+                    merge1.setStateAfter(stateBefore);
+
+                    ifNode.setFalseSuccessor(merge1.endAt(0));
+                    secondIf.setFalseSuccessor(merge1.endAt(1));
+                    merge1.setNext(normalVector);
+
+                    Merge merge2 = new Merge(graph);
+                    merge2.addEnd(new EndNode(graph));
+                    merge2.addEnd(new EndNode(graph));
+                    merge2.setStateAfter(stateAfter);
+
+                    normalVector.setNext(merge2.endAt(0));
+                    reverseVector.setNext(merge2.endAt(1));
+
+                    Return ret = new Return(null, graph);
+                    merge2.setNext(ret);
+                    graph.setReturn(ret);
+                    return graph;
+                }
+            } else if (holderName.equals("Ljava/lang/Float;")) {
+                if (fullName.equals("floatToRawIntBits(F)I") || fullName.equals("floatToIntBits(F)I")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Return ret = new Return(new FPConversionNode(CiKind.Int, new Local(CiKind.Float, 0, graph), graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                } else if (fullName.equals("intBitsToFloat(I)F")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Return ret = new Return(new FPConversionNode(CiKind.Float, new Local(CiKind.Int, 0, graph), graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                }
+            } else if (holderName.equals("Ljava/lang/Double;")) {
+                if (fullName.equals("doubleToRawLongBits(D)J") || fullName.equals("doubleToLongBits(D)J")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Return ret = new Return(new FPConversionNode(CiKind.Long, new Local(CiKind.Double, 0, graph), graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                } else if (fullName.equals("longBitsToDouble(J)D")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Return ret = new Return(new FPConversionNode(CiKind.Double, new Local(CiKind.Long, 0, graph), graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                }
+            } else if (holderName.equals("Ljava/lang/Thread;")) {
+                if (fullName.equals("currentThread()Ljava/lang/Thread;")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Return ret = new Return(new CurrentThread(config.threadObjectOffset, graph), graph);
+                    graph.start().setNext(ret);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                }
+            }
+
+            if (!intrinsicGraphs.containsKey(method)) {
+                intrinsicGraphs.put(method, null);
+            }
+        }
+        return intrinsicGraphs.get(method);
+    }
 }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java	Wed Jul 06 16:51:01 2011 +0200
@@ -1179,7 +1179,6 @@
 
     @Override
     public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type) {
-        assert type.isResolved();
         return new XirSnippet(checkCastTemplates.get(site), receiver, hub);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/ArrayWriteBarrier.java	Wed Jul 06 16:51:01 2011 +0200
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.runtime.nodes;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class ArrayWriteBarrier extends WriteBarrier {
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_OBJECT = 0;
+    private static final int INPUT_LOCATION = 1;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public void setObject(Value n) {
+        inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public LocationNode location() {
+        return (LocationNode) inputs().get(super.inputCount() + INPUT_LOCATION);
+    }
+
+    public void setLocation(LocationNode n) {
+        inputs().set(super.inputCount() + INPUT_LOCATION, n);
+    }
+
+    public ArrayWriteBarrier(Value object, LocationNode index, Graph graph) {
+        super(INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.setObject(object);
+        this.setLocation(index);
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) new LIRGenerator.LIRGeneratorOp() {
+                @Override
+                public void generate(Node n, LIRGenerator generator) {
+                    assert n == ArrayWriteBarrier.this;
+                    CiVariable temp = generator.newVariable(CiKind.Word);
+                    generator.lir().lea(location().createAddress(generator, object()), temp);
+                    ArrayWriteBarrier.this.generateBarrier(temp, generator);
+                }
+            };
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("field write barrier ").print(object());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new ArrayWriteBarrier(null, null, into);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/CurrentThread.java	Wed Jul 06 16:51:01 2011 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.runtime.nodes;
+
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class CurrentThread extends FloatingNode {
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+    private int threadObjectOffset;
+
+    public CurrentThread(int threadObjectOffset, Graph graph) {
+        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.threadObjectOffset = threadObjectOffset;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) new LIRGenerator.LIRGeneratorOp() {
+                @Override
+                public void generate(Node n, LIRGenerator generator) {
+                    CurrentThread conv = (CurrentThread) n;
+                    CiValue result = generator.createResultVariable(conv);
+                    generator.lir().move(new CiAddress(CiKind.Object, AMD64.r15.asValue(CiKind.Word), threadObjectOffset), result);
+                }
+            };
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof CurrentThread;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("currentThread");
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new CurrentThread(threadObjectOffset, into);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FPConversionNode.java	Wed Jul 06 16:51:01 2011 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.runtime.nodes;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class FPConversionNode extends FloatingNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_OBJECT = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public void setValue(Value n) {
+        inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    }
+
+    public FPConversionNode(CiKind kind, Value value, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.setValue(value);
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) new LIRGenerator.LIRGeneratorOp() {
+                @Override
+                public void generate(Node n, LIRGenerator generator) {
+                    FPConversionNode conv = (FPConversionNode) n;
+                    CiValue reg = generator.createResultVariable(conv);
+                    CiValue value = generator.load(conv.value());
+                    CiValue tmp = generator.forceToSpill(value, conv.kind, false);
+                    generator.lir().move(tmp, reg);
+                }
+            };
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return i instanceof FPConversionNode && ((FPConversionNode) i).kind == kind;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("fp conversion node ").print(value());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new FPConversionNode(kind, null, into);
+    }
+}
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java	Wed Jul 06 16:51:01 2011 +0200
@@ -25,13 +25,11 @@
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.ir.*;
-import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.runtime.*;
 import com.sun.cri.ci.*;
 
 
-public final class FieldWriteBarrier extends FixedNodeWithNext {
+public final class FieldWriteBarrier extends WriteBarrier {
     private static final int INPUT_COUNT = 1;
     private static final int INPUT_OBJECT = 0;
 
@@ -54,7 +52,7 @@
     }
 
     public FieldWriteBarrier(Value object, Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.setObject(object);
     }
 
@@ -68,18 +66,8 @@
                 public void generate(Node n, LIRGenerator generator) {
                     assert n == FieldWriteBarrier.this;
                     CiVariable temp = generator.newVariable(CiKind.Word);
-                    HotSpotVMConfig config = CompilerImpl.getInstance().getConfig();
                     generator.lir().move(generator.makeOperand(object()), temp);
-                    generator.lir().unsignedShiftRight(temp, CiConstant.forInt(config.cardtableShift), temp, CiValue.IllegalValue);
-
-                    long startAddress = config.cardtableStartAddress;
-                    int displacement = 0;
-                    if (((int) startAddress) == startAddress) {
-                        displacement = (int) startAddress;
-                    } else {
-                        generator.lir().add(temp, CiConstant.forLong(config.cardtableStartAddress), temp);
-                    }
-                    generator.lir().move(CiConstant.FALSE, new CiAddress(CiKind.Boolean, temp, displacement), (LIRDebugInfo) null);
+                    FieldWriteBarrier.this.generateBarrier(temp, generator);
                 }
             };
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/WriteBarrier.java	Wed Jul 06 16:51:01 2011 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.runtime.nodes;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.runtime.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class WriteBarrier extends FixedNodeWithNext {
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public WriteBarrier(int inputCount, int successorCount, Graph graph) {
+        super(CiKind.Illegal, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    }
+
+
+    protected void generateBarrier(CiValue temp, LIRGenerator generator) {
+        HotSpotVMConfig config = CompilerImpl.getInstance().getConfig();
+        generator.lir().unsignedShiftRight(temp, CiConstant.forInt(config.cardtableShift), temp, CiValue.IllegalValue);
+
+        long startAddress = config.cardtableStartAddress;
+        int displacement = 0;
+        if (((int) startAddress) == startAddress) {
+            displacement = (int) startAddress;
+        } else {
+            generator.lir().add(temp, CiConstant.forLong(config.cardtableStartAddress), temp);
+        }
+        generator.lir().move(CiConstant.FALSE, new CiAddress(CiKind.Boolean, temp, displacement), (LIRDebugInfo) null);
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java	Wed Jul 06 16:31:18 2011 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java	Wed Jul 06 16:51:01 2011 +0200
@@ -50,7 +50,7 @@
             for (Group g : groups) {
                 List<Group> children = new ArrayList<Group>();
                 children.add(g);
-                if(g.getGraphs().size() == 1) {
+                if(false && g.getGraphs().size() == 1) {
                     //g.getGraphs().get(0).setName(g.getName() + " / " + g.getGraphs().get(0).getName());
                     result.add(new Pair<String, List<Group>>("", children));
                 } else {
--- a/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Jul 06 16:31:18 2011 +0200
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Jul 06 16:51:01 2011 +0200
@@ -459,6 +459,7 @@
   } while (should_repeat == true);
 
   if (h_method->method_data() != NULL) {
+    ResourceMark rm(thread);
     ProfileData* pdata = h_method->method_data()->allocate_bci_to_data(current_bci);
     if (pdata != NULL) {
       int tstate0 = pdata->trap_state();
--- a/src/share/vm/runtime/deoptimization.cpp	Wed Jul 06 16:31:18 2011 +0200
+++ b/src/share/vm/runtime/deoptimization.cpp	Wed Jul 06 16:51:01 2011 +0200
@@ -1244,7 +1244,7 @@
 
     if (trap_scope->rethrow_exception()) {
       if (TraceDeoptimization) {
-        tty->print_cr("Exception to be rethrown in the interpreter");
+        tty->print_cr("Exception to be rethrown in the interpreter for method %s::%s at bci %d", instanceKlass::cast(trap_method->method_holder())->name()->as_C_string(), trap_method->name()->as_C_string(), trap_bci);
       }
       GrowableArray<ScopeValue*>* expressions = trap_scope->expressions();
       ScopeValue* topOfStack = expressions->top();
--- a/src/share/vm/runtime/vframeArray.cpp	Wed Jul 06 16:31:18 2011 +0200
+++ b/src/share/vm/runtime/vframeArray.cpp	Wed Jul 06 16:51:01 2011 +0200
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "classfile/vmSymbols.hpp"
+#include "code/scopeDesc.hpp"
 #include "interpreter/interpreter.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
@@ -62,7 +63,7 @@
   _method = vf->method();
   _bci    = vf->raw_bci();
   _reexecute = vf->should_reexecute();
-
+  
   int index;
 
   // Get the monitors off-stack
@@ -126,28 +127,37 @@
 
   // Now the expressions off-stack
   // Same silliness as above
-
-  StackValueCollection *exprs = vf->expressions();
-  _expressions = new StackValueCollection(exprs->size());
-  for(index = 0; index < exprs->size(); index++) {
-    StackValue* value = exprs->at(index);
-    switch(value->type()) {
-      case T_OBJECT:
-        assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
-        // preserve object type
-        _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT ));
-        break;
-      case T_CONFLICT:
-        // A dead stack element.  Will be initialized to null/zero.
-        // This can occur when the compiler emits a state in which stack
-        // elements are known to be dead (because of an imminent exception).
-        _expressions->add( new StackValue());
-        break;
-      case T_INT:
-        _expressions->add( new StackValue(value->get_int()));
-        break;
-      default:
-        ShouldNotReachHere();
+  bool rethrow_exception = vf->scope()->rethrow_exception();
+  if (rethrow_exception) {
+    // (tw) Make sure there are only null pointers on the stack, because the stack values do not correspond to the GC map at the bytecode at which the exception is rethrown.
+    _expressions = new StackValueCollection(vf->method()->max_stack());
+    assert(Thread::current()->has_pending_exception(), "just checking");
+    for (int i=0; i<vf->method()->max_stack(); ++i) {
+      _expressions->add( new StackValue());
+    }
+  } else {
+    StackValueCollection *exprs = vf->expressions();
+    _expressions = new StackValueCollection(exprs->size());
+    for(index = 0; index < exprs->size(); index++) {
+      StackValue* value = exprs->at(index);
+      switch(value->type()) {
+        case T_OBJECT:
+          assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
+          // preserve object type
+          _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT ));
+          break;
+        case T_CONFLICT:
+          // A dead stack element.  Will be initialized to null/zero.
+          // This can occur when the compiler emits a state in which stack
+          // elements are known to be dead (because of an imminent exception).
+          _expressions->add( new StackValue());
+          break;
+        case T_INT:
+          _expressions->add( new StackValue(value->get_int()));
+          break;
+        default:
+          ShouldNotReachHere();
+      }
     }
   }
 }
@@ -314,8 +324,7 @@
   // only unpacks the part of the expression stack not used by callee
   // as parameters. The callee parameters are unpacked as part of the
   // callee locals.
-  int i;
-  for(i = 0; i < expressions()->size(); i++) {
+  for(int i = 0; i < expressions()->size(); i++) {
     StackValue *value = expressions()->at(i);
     intptr_t*   addr  = iframe()->interpreter_frame_expression_stack_at(i);
     switch(value->type()) {
@@ -352,7 +361,7 @@
 
 
   // Unpack the locals
-  for(i = 0; i < locals()->size(); i++) {
+  for(int i = 0; i < locals()->size(); i++) {
     StackValue *value = locals()->at(i);
     intptr_t* addr  = iframe()->interpreter_frame_local_at(i);
     switch(value->type()) {