changeset 3149:03aca60eb99f

Merge
author Gilles Duboscq <gilles.duboscq@oracle.com>
date Tue, 05 Jul 2011 11:42:28 +0200
parents a32be743f046 (current diff) 92b24e9e7e88 (diff)
children 906a2e39495b 4011431b4d85
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java
diffstat 33 files changed, 833 insertions(+), 165 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Tue Jul 05 11:42:28 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/gen/LIRGenerator.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Tue Jul 05 11:42:28 2011 +0200
@@ -201,6 +201,10 @@
         this.operands = new OperandPool(compilation.target);
     }
 
+    public CiTarget target() {
+        return compilation.target;
+    }
+
     public LIRList lir() {
         return lir;
     }
@@ -580,11 +584,7 @@
     }
 
     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);
+        return invoke.stateAfter().duplicateModified(getBeforeInvokeBci(invoke), invoke.stateAfter().rethrowException(), invoke.kind, invoke.arguments().toArray(new Value[0]));
     }
 
     private int getBeforeInvokeBci(Invoke invoke) {
@@ -742,8 +742,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) {
@@ -1074,7 +1077,7 @@
             lastState = fs;
         } else if (block.blockPredecessors().size() == 1) {
             FrameState fs = block.blockPredecessors().get(0).lastState();
-            assert fs != null;
+            //assert fs != null : "B" + block.blockID() + ", pred=B" + block.blockPredecessors().get(0).blockID();
             if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
                 TTY.println("STATE CHANGE (singlePred)");
                 if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
@@ -1461,8 +1464,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
@@ -1676,10 +1682,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/CompilerGraph.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/CompilerGraph.java	Tue Jul 05 11:42:28 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;
     }
 }
--- /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	Tue Jul 05 11:42:28 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 FixedNodeWithNext {
+
+    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	Tue Jul 05 11:42:28 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	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java	Tue Jul 05 11:42:28 2011 +0200
@@ -128,7 +128,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/Condition.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java	Tue Jul 05 11:42:28 2011 +0200
@@ -173,10 +173,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 +204,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	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java	Tue Jul 05 11:42:28 2011 +0200
@@ -179,7 +179,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	Tue Jul 05 11:42:28 2011 +0200
@@ -0,0 +1,165 @@
+/*
+ * 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.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, 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/FixedGuard.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java	Tue Jul 05 11:42:28 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/If.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Tue Jul 05 11:42:28 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
--- /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	Tue Jul 05 11:42:28 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	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java	Tue Jul 05 11:42:28 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	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadField.java	Tue Jul 05 11:42:28 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/Local.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Local.java	Tue Jul 05 11:42:28 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	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java	Tue Jul 05 11:42:28 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/ReadVectorNode.java	Tue Jul 05 11:42:28 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	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java	Tue Jul 05 11:42:28 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/Value.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Tue Jul 05 11:42:28 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;
     }
 
--- /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	Tue Jul 05 11:42:28 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/phases/DeadCodeEliminationPhase.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Tue Jul 05 11:42:28 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	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DuplicationPhase.java	Tue Jul 05 11:42:28 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/EscapeAnalysisPhase.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java	Tue Jul 05 11:42:28 2011 +0200
@@ -152,7 +152,7 @@
 
                     Node current;
                     if (block.firstNode() instanceof StartNode) {
-                        current = ((StartNode) block.firstNode()).start();
+                        current = ((StartNode) block.firstNode()).next();
                     } else {
                         current = block.firstNode();
                     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Tue Jul 05 11:42:28 2011 +0200
@@ -172,7 +172,7 @@
         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
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Tue Jul 05 11:42:28 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,33 +323,41 @@
             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 && graph.getNodes(Merge.class).iterator().hasNext()) {
+                WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(invoke.graph());
+                checkpoint.setStateAfter(invoke.stateAfter());
+                checkpoint.setNext(invoke.next());
+                invoke.setNext(checkpoint);
+            }
         }
         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) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java	Tue Jul 05 11:42:28 2011 +0200
@@ -71,8 +71,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;
             }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java	Tue Jul 05 11:42:28 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	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Tue Jul 05 11:42:28 2011 +0200
@@ -69,12 +69,12 @@
                 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) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Tue Jul 05 11:42:28 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
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java	Tue Jul 05 11:42:28 2011 +0200
@@ -58,7 +58,7 @@
         int index = 0;
         if (!isStatic(method.accessFlags())) {
             // add the receiver and assume it is non null
-            Local local = new Local(method.holder().kind(), javaIndex, graph.start(), graph);
+            Local local = new Local(method.holder().kind(), javaIndex, graph);
             local.setDeclaredType(method.holder());
             storeLocal(javaIndex, local);
             javaIndex = 1;
@@ -70,7 +70,7 @@
         for (int i = 0; i < max; i++) {
             RiType type = sig.argumentTypeAt(i, accessingClass);
             CiKind kind = type.kind().stackKind();
-            Local local = new Local(kind, index, graph.start(), graph);
+            Local local = new Local(kind, index, graph);
             if (type.isResolved()) {
                 local.setDeclaredType(type);
             }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java	Tue Jul 05 11:42:28 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	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java	Tue Jul 05 11:42:28 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	Tue Jul 05 11:39:40 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Tue Jul 05 11:42:28 2011 +0200
@@ -26,6 +26,9 @@
 import java.lang.reflect.*;
 import java.util.*;
 
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.graph.*;
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.runtime.nodes.*;
@@ -46,6 +49,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) {
@@ -276,4 +280,111 @@
             field.replaceAndDelete(memoryWrite);
         }
     }
+
+    @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);
+                    Local 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;
+                    }
+
+                    // 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);
+
+                    // 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);
+
+                    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));
+
+                    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));
+
+                    normalVector.setNext(merge2.endAt(0));
+                    reverseVector.setNext(merge2.endAt(1));
+
+                    Return ret = new Return(null, graph);
+                    merge2.setNext(ret);
+                    graph.setReturn(ret);
+                    return graph;
+                }
+            }
+
+            if (!intrinsicGraphs.containsKey(method)) {
+                intrinsicGraphs.put(method, null);
+            }
+        }
+        return intrinsicGraphs.get(method);
+    }
 }