changeset 5768:99567466b008

Merge.
author Lukas Stadler <lukas.stadler@jku.at>
date Thu, 05 Jul 2012 16:54:45 +0200
parents 5967805da8f5 (current diff) 8d0a6bceb112 (diff)
children 772118da9f68
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformPhase.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/VMAdapter.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewTypeArrayNode.java
diffstat 122 files changed, 4053 insertions(+), 1779 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Thu Jul 05 16:54:45 2012 +0200
@@ -44,14 +44,6 @@
     String disassemble(CodeInfo code, CompilationResult tm);
 
     /**
-     * Returns the disassembly of the given method in a {@code javap}-like format.
-     *
-     * @param method the method that should be disassembled
-     * @return the disassembly. This will be of length 0 if the runtime does not support disassembling.
-     */
-    String disassemble(ResolvedJavaMethod method);
-
-    /**
      * Gets the register configuration to use when compiling a given method.
      *
      * @param method the top level method of a compilation
--- a/graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/Interpreter.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/Interpreter.java	Thu Jul 05 16:54:45 2012 +0200
@@ -25,5 +25,6 @@
 import com.oracle.graal.api.meta.*;
 
 public interface Interpreter extends VirtualMachineComponent {
-    Object execute(ResolvedJavaMethod method, Object... arguments);
+    boolean initialize(String args);
+    Object execute(ResolvedJavaMethod method, Object... arguments) throws Throwable;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/RuntimeInterpreterInterface.java	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.api.interpreter;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Please note: The parameters of the interface are currently in reversed order
+ * since it was derived from the java ByteCodeInterpreter implementation. There
+ * it was simpler to use the parameters in reversed order since they are popped from
+ * the stack in reversed order.
+ */
+public interface RuntimeInterpreterInterface {
+
+    Object invoke(ResolvedJavaMethod method, Object... args);
+
+    void monitorEnter(Object value);
+
+    void monitorExit(Object value);
+
+    Object newObject(ResolvedJavaType type) throws InstantiationException;
+
+    Object getFieldObject(Object base, ResolvedJavaField field);
+
+    boolean getFieldBoolean(Object base, ResolvedJavaField field);
+
+    byte getFieldByte(Object base, ResolvedJavaField field);
+
+    char getFieldChar(Object base, ResolvedJavaField field);
+
+    short getFieldShort(Object base, ResolvedJavaField field);
+
+    int getFieldInt(Object base, ResolvedJavaField field);
+
+    long getFieldLong(Object base, ResolvedJavaField field);
+
+    double getFieldDouble(Object base, ResolvedJavaField field);
+
+    float getFieldFloat(Object base, ResolvedJavaField field);
+
+    void setFieldObject(Object value, Object base, ResolvedJavaField field);
+
+    void setFieldInt(int value, Object base, ResolvedJavaField field);
+
+    void setFieldFloat(float value, Object base, ResolvedJavaField field);
+
+    void setFieldDouble(double value, Object base, ResolvedJavaField field);
+
+    void setFieldLong(long value, Object base, ResolvedJavaField field);
+
+    byte getArrayByte(long index, Object array);
+
+    char getArrayChar(long index, Object array);
+
+    short getArrayShort(long index, Object array);
+
+    int getArrayInt(long index, Object array);
+
+    long getArrayLong(long index, Object array);
+
+    double getArrayDouble(long index, Object array);
+
+    float getArrayFloat(long index, Object array);
+
+    Object getArrayObject(long index, Object array);
+
+    void setArrayByte(byte value, long index, Object array);
+
+    void setArrayChar(char value, long index, Object array);
+
+    void setArrayShort(short value, long index, Object array);
+
+    void setArrayInt(int value, long index, Object array);
+
+    void setArrayLong(long value, long index, Object array);
+
+    void setArrayFloat(float value, long index, Object array);
+
+    void setArrayDouble(double value, long index, Object array);
+
+    void setArrayObject(Object value, long index, Object array);
+
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaType.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaType.java	Thu Jul 05 16:54:45 2012 +0200
@@ -65,7 +65,9 @@
 
     /**
      * For array types, gets the type of the components.
-     * @return the component type of this array type
+     * This will be null if this is not an array type.
+     *
+     * @return the component type of this type if it is an array type otherwise null
      */
     JavaType componentType();
 
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Thu Jul 05 16:54:45 2012 +0200
@@ -25,6 +25,7 @@
 import static java.lang.reflect.Modifier.*;
 
 import java.lang.annotation.*;
+import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
@@ -308,6 +309,27 @@
 
 
     /**
+     * Gets the annotations of a particular type for the formal parameters of a given method.
+     *
+     * @param annotationClass the Class object corresponding to the annotation type
+     * @param method the method for which a parameter annotations are being requested
+     * @return the annotation of type {@code annotationClass} (if any) for each formal parameter present
+     */
+    public static <T extends Annotation> T[] getParameterAnnotations(Class<T> annotationClass, ResolvedJavaMethod method) {
+        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+        @SuppressWarnings("unchecked")
+        T[] result = (T[]) Array.newInstance(annotationClass, parameterAnnotations.length);
+        for (int i = 0; i < parameterAnnotations.length; i++) {
+            for (Annotation a : parameterAnnotations[i]) {
+                if (a.annotationType() == annotationClass) {
+                    result[i] = annotationClass.cast(a);
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
      * Gets the annotation of a particular type for a formal parameter of a given method.
      *
      * @param annotationClass the Class object corresponding to the annotation type
@@ -328,7 +350,6 @@
         return null;
     }
 
-
     /**
      * Convenient shortcut for calling {@link #appendLocation(StringBuilder, ResolvedJavaMethod, int)} without having to supply a
      * a {@link StringBuilder} instance and convert the result to a string.
--- a/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/BigBangTest.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/BigBangTest.java	Thu Jul 05 16:54:45 2012 +0200
@@ -30,14 +30,14 @@
     public void helloWorldTest() {
         BootImageGenerator generator = new BootImageGenerator();
         generator.addEntryMethod(TestPrograms.class, "helloWorldTest");
-        Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{3, 118, 58, 21});
+        Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{3, 148, 66, 24});
     }
 
     @Test
     public void formattedOutputTest() {
         BootImageGenerator generator = new BootImageGenerator();
         generator.addEntryMethod(TestPrograms.class, "formattedOutputTest");
-        Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{15, 979, 346, 98});
+        Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{19, 1668, 611, 179});
     }
 
 
@@ -60,6 +60,13 @@
     public void arrayListTest() {
         BootImageGenerator generator = new BootImageGenerator();
         generator.addEntryMethod(TestPrograms.class, "arrayListTest");
+        Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{2, 28, 5, 3});
+    }
+
+    @Test
+    public void arrayListTestWithCalls() {
+        BootImageGenerator generator = new BootImageGenerator();
+        generator.addEntryMethod(TestPrograms.class, "arrayListTestWithCalls");
         Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{2, 20, 3, 2});
     }
 }
--- a/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/TestPrograms.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/TestPrograms.java	Thu Jul 05 16:54:45 2012 +0200
@@ -53,8 +53,26 @@
         newArr[0].testMethod();
     }
 
+    @SuppressWarnings("unchecked")
+    public static void arrayListTestWithCalls() {
+        ArrayList list = createNewArrayList();
+        list.add(new TestObject());
+        TestObject[] newArr = (TestObject[]) list.toArray(new TestObject[0]);
+        TestObject t2 = newArr[0].testMethod();
+        t2.testMethod2();
+    }
+
+    private static ArrayList createNewArrayList() {
+        return new ArrayList();
+    }
+
     public static class TestObject {
-        public void testMethod() {
+        public TestObject testMethod() {
+            return new TestObject();
+        }
+
+        public void testMethod2() {
+
         }
     }
 }
--- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ArrayTypeElement.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ArrayTypeElement.java	Thu Jul 05 16:54:45 2012 +0200
@@ -52,6 +52,13 @@
         if (type == null) {
             System.out.println("FATAL error: Array access without type!");
             System.out.println(load.array());
+            if (load.array() instanceof ValueProxyNode) {
+                ValueProxyNode valueProxyNode = (ValueProxyNode) load.array();
+                System.out.println("value proxy node stamp " + valueProxyNode.stamp());
+                System.out.println("value proxy node stamp type " + valueProxyNode.objectStamp().type());
+                System.out.println("value proxy source: " + valueProxyNode.value());
+                System.out.println("value proxy source stamp: " + valueProxyNode.value().stamp());
+            }
             System.out.println(((StructuredGraph) load.graph()).method());
             System.exit(-1);
         }
--- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/InvokeElement.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/InvokeElement.java	Thu Jul 05 16:54:45 2012 +0200
@@ -68,6 +68,7 @@
             ResolvedJavaMethod method = methodCallTarget.targetMethod();
             concreteTargets.add(method);
             MethodElement processedMethod = bb.getProcessedMethod(method);
+            processedMethod.addUsage(bb, this.methodCallTarget.invoke().node());
             processedMethod.postParseGraph(bb);
         }
     }
@@ -94,6 +95,7 @@
                                 bb.getProcessedMethod(method).getParameter(i).postUnionTypes(bb, null, newSeenTypesTemp);
                             }
                         }
+                        processedMethod.addUsage(bb, this.methodCallTarget.invoke().node());
                     }
 
                     // Register new type for receiver.
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Jul 05 16:54:45 2012 +0200
@@ -188,18 +188,17 @@
         if (GraalOptions.CheckCastElimination) {
             new CheckCastEliminationPhase().apply(graph);
         }
+        if (GraalOptions.OptCanonicalizer) {
+            new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+        }
+        if (GraalOptions.OptCanonicalizer) {
+            new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+        }
 
         if (GraalOptions.OptLoopTransform) {
             new LoopTransformLowPhase().apply(graph);
         }
         new RemoveValueProxyPhase().apply(graph);
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
-        }
-        if (GraalOptions.CheckCastElimination) {
-            new CheckCastEliminationPhase().apply(graph);
-        }
-
 
         plan.runPhases(PhasePosition.MID_LEVEL, graph);
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Thu Jul 05 16:54:45 2012 +0200
@@ -97,12 +97,13 @@
     //rematerialize settings
     public static float   MinimumUsageProbability            = 0.95f;
 
-    //loop transform settings
-    public static float   MinimumPeelProbability             = 0.35f;
+    //loop transform settings TODO (gd) tune
+    public static boolean LoopPeeling                        = true;
     public static boolean ReassociateInvariants              = true;
     public static boolean FullUnroll                         = true;
-    public static int     FullUnrollMaxNodes                 = 150; // TODO (gd) tune
     public static boolean LoopUnswitch                       = ____;
+    public static int     FullUnrollMaxNodes                 = 150;
+    public static float   MinimumPeelProbability             = 0.35f;
     public static int     LoopUnswitchMaxIncrease            = 50;
     public static int     LoopUnswitchUncertaintyBoost       = 5;
 
@@ -263,6 +264,7 @@
      */
     public static String HIRLowerCheckcast = "";
     public static String HIRLowerNewInstance = "";
+    public static String HIRLowerNewArray = "";
 
     static {
         // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this)
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Jul 05 16:54:45 2012 +0200
@@ -31,9 +31,9 @@
 import java.util.Map.Entry;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CompilationResult.*;
+import com.oracle.graal.api.code.CompilationResult.Mark;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.JavaType.*;
+import com.oracle.graal.api.meta.JavaType.Representation;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.debug.*;
@@ -590,7 +590,7 @@
     }
 
     @Override
-    public void visitNewTypeArray(NewTypeArrayNode x) {
+    public void visitNewPrimitiveArray(NewPrimitiveArrayNode x) {
         XirArgument length = toXirArgument(x.length());
         XirSnippet snippet = xir.genNewArray(site(x), length, x.elementType().kind(), null, null);
         emitXir(snippet, x, state(), true);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java	Thu Jul 05 16:54:45 2012 +0200
@@ -89,7 +89,13 @@
     public abstract NodeIterable<Node> nodes();
 
     public StructuredGraph graph() {
-        return (StructuredGraph) loop.loopBegin().graph();
+        LoopEx l;
+        if (isDuplicate()) {
+            l = original().loop();
+        } else {
+            l = loop();
+        }
+        return (StructuredGraph) l.loopBegin().graph();
     }
 
     protected abstract DuplicationReplacement getDuplicationReplacement();
@@ -99,11 +105,13 @@
     protected void patchNodes(final DuplicationReplacement dataFix) {
         if (isDuplicate() && !nodesReady) {
             assert !original.isDuplicate();
-            final DuplicationReplacement cfgFix = getDuplicationReplacement();
+            final DuplicationReplacement cfgFix = original().getDuplicationReplacement();
             DuplicationReplacement dr;
-            if (cfgFix == null) {
+            if (cfgFix == null && dataFix != null) {
                 dr = dataFix;
-            } else {
+            } else if (cfgFix != null && dataFix == null) {
+                dr = cfgFix;
+            } else if (cfgFix != null && dataFix != null) {
                 dr = new DuplicationReplacement() {
                     @Override
                     public Node replacement(Node o) {
@@ -119,8 +127,15 @@
                         return o;
                     }
                 };
+            } else {
+                dr = new DuplicationReplacement() {
+                    @Override
+                    public Node replacement(Node o) {
+                        return o;
+                    }
+                };
             }
-            duplicationMap = graph().addDuplicates(nodes(), dr);
+            duplicationMap = graph().addDuplicates(original().nodes(), dr);
             finishDuplication();
             nodesReady = true;
         } else {
@@ -221,11 +236,13 @@
         StructuredGraph graph = graph();
         for (BeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().lirLoop().exits)) {
             FixedNode next = earlyExit.next();
-            if (earlyExit.isDeleted() || !this.contains(earlyExit)) {
+            if (earlyExit.isDeleted() || !this.original().contains(earlyExit)) {
                 continue;
             }
             BeginNode newEarlyExit = getDuplicatedNode(earlyExit);
-            assert newEarlyExit != null;
+            if (newEarlyExit == null) {
+                continue;
+            }
             MergeNode merge = graph.add(new MergeNode());
             merge.setProbability(next.probability());
             EndNode originalEnd = graph.add(new EndNode());
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentInside.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentInside.java	Thu Jul 05 16:54:45 2012 +0200
@@ -41,7 +41,7 @@
      * In the unrolling case they will be used as the value that replace the loop-phis of the duplicated inside fragment
      */
     private Map<PhiNode, ValueNode> mergedInitializers;
-    private final DuplicationReplacement dataFix = new DuplicationReplacement() {
+    private final DuplicationReplacement dataFixBefore = new DuplicationReplacement() {
         @Override
         public Node replacement(Node oriInput) {
             if (!(oriInput instanceof ValueNode)) {
@@ -56,7 +56,7 @@
     }
 
     public LoopFragmentInside(LoopFragmentInside original) {
-        super(original.loop(), original);
+        super(null, original);
     }
 
     @Override
@@ -76,11 +76,16 @@
     }
 
     @Override
+    public LoopEx loop() {
+        assert !this.isDuplicate();
+        return super.loop();
+    }
+
+    @Override
     public void insertBefore(LoopEx loop) {
-        if (this.loop() != loop) {
-            throw new UnsupportedOperationException();
-        }
-        patchNodes(dataFix);
+        assert this.isDuplicate() && this.original().loop() == loop;
+
+        patchNodes(dataFixBefore);
 
         BeginNode end = mergeEnds();
 
@@ -88,7 +93,7 @@
 
         mergeEarlyExits();
 
-        BeginNode entry = getDuplicatedNode(this.loop().loopBegin());
+        BeginNode entry = getDuplicatedNode(loop.loopBegin());
         FrameState state = entry.stateAfter();
         if (state != null) {
             entry.setStateAfter(null);
@@ -137,7 +142,6 @@
     @Override
     protected void finishDuplication() {
         // TODO (gd) ?
-
     }
 
     private void patchPeeling(LoopFragmentInside peel) {
@@ -187,7 +191,8 @@
      * @return corresponding value in the peel
      */
     private ValueNode prim(ValueNode b) {
-        LoopBeginNode loopBegin = loop().loopBegin();
+        assert isDuplicate();
+        LoopBeginNode loopBegin = original().loop().loopBegin();
         if (loopBegin.isPhiAtMerge(b)) {
             PhiNode phi = (PhiNode) b;
             return phi.valueAt(loopBegin.forwardEnd());
@@ -203,9 +208,10 @@
     }
 
     private BeginNode mergeEnds() {
+        assert isDuplicate();
         List<EndNode> endsToMerge = new LinkedList<>();
         Map<EndNode, LoopEndNode> reverseEnds = new HashMap<>(); // map peel's exit to the corresponding loop exits
-        LoopBeginNode loopBegin = loop().loopBegin();
+        LoopBeginNode loopBegin = original().loop().loopBegin();
         for (LoopEndNode le : loopBegin.loopEnds()) {
             EndNode duplicate = getDuplicatedNode(le);
             if (duplicate != null) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentWhole.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentWhole.java	Thu Jul 05 16:54:45 2012 +0200
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.lir.cfg.*;
+import com.oracle.graal.nodes.*;
 
 
 public class LoopFragmentWhole extends LoopFragment {
@@ -34,10 +35,23 @@
         super(loop);
     }
 
+    public LoopFragmentWhole(LoopFragmentWhole original) {
+        super(null, original);
+    }
+
     @Override
     public LoopFragmentWhole duplicate() {
-        // TODO (gd) do not forget to make a FULL loop : do not forget the forward end which is not part of the original loop stricto sensus
-        return null;
+        LoopFragmentWhole loopFragmentWhole = new LoopFragmentWhole(this);
+        loopFragmentWhole.reify();
+        return loopFragmentWhole;
+    }
+
+    private void reify() {
+        assert this.isDuplicate();
+
+        patchNodes(null);
+
+        mergeEarlyExits();
     }
 
     @Override
@@ -51,13 +65,30 @@
 
     @Override
     protected DuplicationReplacement getDuplicationReplacement() {
-        return null;
+        final FixedNode entry = loop().entryPoint();
+        final Graph graph = this.graph();
+        return new DuplicationReplacement() {
+            @Override
+            public Node replacement(Node o) {
+                if (o == entry) {
+                    return graph.add(new EndNode());
+                }
+                return o;
+            }
+        };
+    }
+
+    public FixedNode entryPoint() {
+        if (isDuplicate()) {
+            LoopBeginNode newLoopBegin = getDuplicatedNode(original().loop().loopBegin());
+            return newLoopBegin.forwardEnd();
+        }
+        return loop().entryPoint();
     }
 
     @Override
     protected void finishDuplication() {
-        // TODO Auto-generated method stub
-
+        // TODO (gd) ?
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformations.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformations.java	Thu Jul 05 16:54:45 2012 +0200
@@ -23,13 +23,43 @@
 package com.oracle.graal.compiler.loop;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
 
 
 public abstract class LoopTransformations {
     private static final int UNROLL_LIMIT = GraalOptions.FullUnrollMaxNodes * 2;
+    private static final SimplifierTool simplifier = new SimplifierTool() {
+        @Override
+        public TargetDescription target() {
+            return null;
+        }
+        @Override
+        public CodeCacheProvider runtime() {
+            return null;
+        }
+        @Override
+        public boolean isImmutable(Constant objectConstant) {
+            return false;
+        }
+        @Override
+        public Assumptions assumptions() {
+            return null;
+        }
+        @Override
+        public void deleteBranch(FixedNode branch) {
+            branch.predecessor().replaceFirstSuccessor(branch, null);
+            GraphUtil.killCFG(branch);
+        }
+        @Override
+        public void addToWorkList(Node node) {
+        }
+    };
 
     private LoopTransformations() {
         // does not need to be instantiated
@@ -47,7 +77,7 @@
         loop.inside().duplicate().insertBefore(loop);
     }
 
-    public static void fullUnroll(LoopEx loop, CodeCacheProvider runtime) {
+    public static void fullUnroll(LoopEx loop, MetaAccessProvider runtime) {
         //assert loop.isCounted(); //TODO (gd) strenghten : counted with known trip count
         int iterations = 0;
         LoopBeginNode loopBegin = loop.loopBegin();
@@ -64,16 +94,19 @@
 
     public static void unswitch(LoopEx loop, IfNode ifNode) {
         // duplicate will be true case, original will be false case
-        LoopFragmentWhole duplicateLoop = loop.whole().duplicate();
+        LoopFragmentWhole originalLoop = loop.whole();
+        LoopFragmentWhole duplicateLoop = originalLoop.duplicate();
         StructuredGraph graph = (StructuredGraph) ifNode.graph();
         BeginNode tempBegin = graph.add(new BeginNode());
-        loop.entryPoint().replaceAtPredecessor(tempBegin);
+        originalLoop.entryPoint().replaceAtPredecessor(tempBegin);
         double takenProbability = ifNode.probability(ifNode.blockSuccessorIndex(ifNode.trueSuccessor()));
-        IfNode newIf = graph.add(new IfNode(ifNode.compare(), duplicateLoop.loop().entryPoint(), loop.entryPoint(), takenProbability, ifNode.leafGraphId()));
+        IfNode newIf = graph.add(new IfNode(ifNode.compare(), duplicateLoop.entryPoint(), originalLoop.entryPoint(), takenProbability, ifNode.leafGraphId()));
         tempBegin.setNext(newIf);
         ifNode.setCompare(graph.unique(ConstantNode.forBoolean(false, graph)));
         IfNode duplicateIf = duplicateLoop.getDuplicatedNode(ifNode);
         duplicateIf.setCompare(graph.unique(ConstantNode.forBoolean(true, graph)));
+        ifNode.simplify(simplifier);
+        duplicateIf.simplify(simplifier);
         // TODO (gd) probabilities need some amount of fixup.. (probably also in other transforms)
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java	Thu Jul 05 16:54:45 2012 +0200
@@ -45,14 +45,14 @@
     private final int newNodesMark;
     private final TargetDescription target;
     private final Assumptions assumptions;
-    private final CodeCacheProvider runtime;
+    private final MetaAccessProvider runtime;
     private final IsImmutablePredicate immutabilityPredicate;
     private final Iterable<Node> initWorkingSet;
 
     private NodeWorkList workList;
     private Tool tool;
 
-    public CanonicalizerPhase(TargetDescription target, CodeCacheProvider runtime, Assumptions assumptions) {
+    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) {
         this(target, runtime, assumptions, null, 0, null);
     }
 
@@ -63,7 +63,7 @@
      * @param workingSet the initial working set of nodes on which the canonicalizer works, should be an auto-grow node bitmap
      * @param immutabilityPredicate
      */
-    public CanonicalizerPhase(TargetDescription target, CodeCacheProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, IsImmutablePredicate immutabilityPredicate) {
+    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, IsImmutablePredicate immutabilityPredicate) {
         this(target, runtime, assumptions, workingSet, 0, immutabilityPredicate);
     }
 
@@ -71,11 +71,11 @@
      * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by
      *            this mark are processed otherwise all nodes in the graph are processed
      */
-    public CanonicalizerPhase(TargetDescription target, CodeCacheProvider runtime, Assumptions assumptions, int newNodesMark, IsImmutablePredicate immutabilityPredicate) {
+    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, IsImmutablePredicate immutabilityPredicate) {
         this(target, runtime, assumptions, null, newNodesMark, immutabilityPredicate);
     }
 
-    private CanonicalizerPhase(TargetDescription target, CodeCacheProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, IsImmutablePredicate immutabilityPredicate) {
+    private CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, IsImmutablePredicate immutabilityPredicate) {
         this.newNodesMark = newNodesMark;
         this.target = target;
         this.assumptions = assumptions;
@@ -255,12 +255,12 @@
     private static final class Tool implements SimplifierTool {
 
         private final NodeWorkList nodeWorkSet;
-        private final CodeCacheProvider runtime;
+        private final MetaAccessProvider runtime;
         private final TargetDescription target;
         private final Assumptions assumptions;
         private final IsImmutablePredicate immutabilityPredicate;
 
-        public Tool(NodeWorkList nodeWorkSet, CodeCacheProvider runtime, TargetDescription target, Assumptions assumptions, IsImmutablePredicate immutabilityPredicate) {
+        public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, TargetDescription target, Assumptions assumptions, IsImmutablePredicate immutabilityPredicate) {
             this.nodeWorkSet = nodeWorkSet;
             this.runtime = runtime;
             this.target = target;
@@ -291,7 +291,7 @@
         }
 
         @Override
-        public CodeCacheProvider runtime() {
+        public MetaAccessProvider runtime() {
             return runtime;
         }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformHighPhase.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformHighPhase.java	Thu Jul 05 16:54:45 2012 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.compiler.phases;
 
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.loop.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
@@ -31,12 +32,14 @@
     @Override
     protected void run(StructuredGraph graph) {
         if (graph.hasLoops()) {
-            LoopsData data = new LoopsData(graph);
-            for (LoopEx loop : data.outterFirst()) {
-                if (LoopPolicies.shouldPeel(loop)) {
-                    Debug.log("Peeling %s", loop);
-                    LoopTransformations.peel(loop);
-                    Debug.dump(graph, "After peeling %s", loop);
+            if (GraalOptions.LoopPeeling) {
+                LoopsData data = new LoopsData(graph);
+                for (LoopEx loop : data.outterFirst()) {
+                    if (LoopPolicies.shouldPeel(loop)) {
+                        Debug.log("Peeling %s", loop);
+                        LoopTransformations.peel(loop);
+                        Debug.dump(graph, "After peeling %s", loop);
+                    }
                 }
             }
         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformLowPhase.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformLowPhase.java	Thu Jul 05 16:54:45 2012 +0200
@@ -25,7 +25,6 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.loop.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
 public class LoopTransformLowPhase extends Phase {
@@ -46,7 +45,6 @@
                 });
             }
             if (GraalOptions.LoopUnswitch) {
-                NodeBitMap unswitchedDebug = graph.createNodeBitMap();
                 boolean unswitched;
                 do {
                     unswitched = false;
@@ -54,12 +52,11 @@
                     for (LoopEx loop : dataUnswitch.loops()) {
                         if (LoopPolicies.shouldTryUnswitch(loop)) {
                             IfNode ifNode = LoopTransformations.findUnswitchableIf(loop);
-                            if (ifNode != null && !unswitchedDebug.isMarked(ifNode) && LoopPolicies.shouldUnswitch(loop, ifNode)) {
-                                unswitchedDebug.mark(ifNode);
+                            if (ifNode != null && LoopPolicies.shouldUnswitch(loop, ifNode)) {
                                 Debug.log("Unswitching %s at %s [%f - %f]", loop, ifNode, ifNode.probability(0), ifNode.probability(1));
-                                //LoopTransformations.unswitch(loop, ifNode);
+                                LoopTransformations.unswitch(loop, ifNode);
                                 UNSWITCHED.increment();
-                                //Debug.dump(graph, "After unswitch %s", loop);
+                                Debug.dump(graph, "After unswitch %s", loop);
                                 unswitched = true;
                                 break;
                             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformPhase.java	Thu Jul 05 16:54:00 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.loop.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.nodes.*;
-
-public class LoopTransformPhase extends Phase {
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        if (graph.hasLoops()) {
-            LoopsData data = new LoopsData(graph);
-            for (LoopEx loop : data.outterFirst()) {
-                double entryProbability = loop.loopBegin().forwardEnd().probability();
-                if (entryProbability > GraalOptions.MinimumPeelProbability
-                                && loop.size() + graph.getNodeCount() < GraalOptions.MaximumDesiredSize) {
-                    Debug.log("Peeling %s", loop);
-                    LoopTransformations.peel(loop);
-                    Debug.dump(graph, "After peeling %s", loop);
-                }
-            }
-        }
-    }
-
-
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Thu Jul 05 16:54:45 2012 +0200
@@ -25,6 +25,7 @@
 import java.lang.reflect.*;
 import com.oracle.graal.api.*;
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.interpreter.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.target.*;
@@ -52,6 +53,7 @@
     private HotSpotRuntime runtime;
     private GraalCompiler compiler;
     private TargetDescription target;
+    private HotSpotRuntimeInterpreterInterface runtimeInterpreterInterface;
     private volatile HotSpotGraphCache cache;
 
     private final HotSpotVMConfig config;
@@ -176,6 +178,13 @@
         return compilerToVm.Signature_lookupType(returnType, accessingClass, eagerResolve);
     }
 
+    public HotSpotRuntimeInterpreterInterface getRuntimeInterpreterInterface() {
+        if (runtimeInterpreterInterface == null) {
+            runtimeInterpreterInterface = new HotSpotRuntimeInterpreterInterface(getRuntime());
+        }
+        return runtimeInterpreterInterface;
+    }
+
     public HotSpotRuntime getRuntime() {
         if (runtime == null) {
             runtime = new HotSpotRuntime(config, this);
@@ -210,6 +219,12 @@
         if (clazz == GraalCompiler.class) {
             return (T) getCompiler();
         }
+        if (clazz == MetaAccessProvider.class) {
+            return (T) getRuntime();
+        }
+        if (clazz == RuntimeInterpreterInterface.class) {
+            return (T) getRuntimeInterpreterInterface();
+        }
         return null;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeInterpreterInterface.java	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot;
+
+import java.lang.reflect.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.interpreter.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.meta.*;
+
+public class HotSpotRuntimeInterpreterInterface implements RuntimeInterpreterInterface {
+
+    private static final Unsafe unsafe = loadUnsafe();
+
+    private final MetaAccessProvider metaProvider;
+
+    public HotSpotRuntimeInterpreterInterface(MetaAccessProvider metaProvider) {
+        this.metaProvider = metaProvider;
+    }
+
+    public native Object invoke(ResolvedJavaMethod method, Object... args);
+
+    public void monitorEnter(Object value) {
+        nullCheck(value);
+        unsafe.monitorEnter(value);
+    }
+
+    public void monitorExit(Object value) {
+        nullCheck(value);
+        unsafe.monitorExit(value);
+    }
+
+    public Object newObject(ResolvedJavaType type) throws InstantiationException {
+        return unsafe.allocateInstance(type.toJava());
+    }
+
+    public Object getFieldObject(Object base, ResolvedJavaField field) {
+        long offset = resolveOffset(field);
+        if (isVolatile(field)) {
+            return unsafe.getObjectVolatile(resolveBase(base, field), offset);
+        } else {
+            return unsafe.getObject(resolveBase(base, field), offset);
+        }
+    }
+
+    public boolean getFieldBoolean(Object base, ResolvedJavaField field) {
+        long offset = resolveOffset(field);
+        if (isVolatile(field)) {
+            return unsafe.getBooleanVolatile(resolveBase(base, field), offset);
+        } else {
+            return unsafe.getBoolean(resolveBase(base, field), offset);
+        }
+    }
+
+    public byte getFieldByte(Object base, ResolvedJavaField field) {
+        long offset = resolveOffset(field);
+        if (isVolatile(field)) {
+            return unsafe.getByteVolatile(resolveBase(base, field), offset);
+        } else {
+            return unsafe.getByte(resolveBase(base, field), offset);
+        }
+    }
+
+    public char getFieldChar(Object base, ResolvedJavaField field) {
+        long offset = resolveOffset(field);
+        if (isVolatile(field)) {
+            return unsafe.getCharVolatile(resolveBase(base, field), offset);
+        } else {
+            return unsafe.getChar(resolveBase(base, field), offset);
+        }
+    }
+
+    public short getFieldShort(Object base, ResolvedJavaField field) {
+        long offset = resolveOffset(field);
+        if (isVolatile(field)) {
+            return unsafe.getShortVolatile(resolveBase(base, field), offset);
+        } else {
+            return unsafe.getShort(resolveBase(base, field), offset);
+        }
+    }
+
+    public int getFieldInt(Object base, ResolvedJavaField field) {
+        long offset = resolveOffset(field);
+        if (isVolatile(field)) {
+            return unsafe.getIntVolatile(resolveBase(base, field), offset);
+        } else {
+            return unsafe.getInt(resolveBase(base, field), offset);
+        }
+    }
+
+    public long getFieldLong(Object base, ResolvedJavaField field) {
+        long offset = resolveOffset(field);
+        if (isVolatile(field)) {
+            return unsafe.getLongVolatile(resolveBase(base, field), offset);
+        } else {
+            return unsafe.getLong(resolveBase(base, field), offset);
+        }
+    }
+
+    public double getFieldDouble(Object base, ResolvedJavaField field) {
+        long offset = resolveOffset(field);
+        if (isVolatile(field)) {
+            return unsafe.getDoubleVolatile(resolveBase(base, field), offset);
+        } else {
+            return unsafe.getDouble(resolveBase(base, field), offset);
+        }
+    }
+
+    public float getFieldFloat(Object base, ResolvedJavaField field) {
+        long offset = resolveOffset(field);
+        if (isVolatile(field)) {
+            return unsafe.getFloatVolatile(resolveBase(base, field), offset);
+        } else {
+            return unsafe.getFloat(resolveBase(base, field), offset);
+        }
+    }
+
+    public void setFieldObject(Object value, Object base, ResolvedJavaField field) {
+        long offset = resolveOffset(field);
+        if (isVolatile(field)) {
+            unsafe.putObjectVolatile(resolveBase(base, field), offset, value);
+        } else {
+            unsafe.putObject(resolveBase(base, field), offset, value);
+        }
+    }
+
+    public void setFieldInt(int value, Object base, ResolvedJavaField field) {
+        long offset = resolveOffset(field);
+        if (isVolatile(field)) {
+            unsafe.putIntVolatile(resolveBase(base, field), offset, value);
+        } else {
+            unsafe.putInt(resolveBase(base, field), offset, value);
+        }
+    }
+
+
+    public void setFieldFloat(float value, Object base, ResolvedJavaField field) {
+        long offset = resolveOffset(field);
+        if (isVolatile(field)) {
+            unsafe.putFloatVolatile(resolveBase(base, field), offset, value);
+        } else {
+            unsafe.putFloat(resolveBase(base, field), offset, value);
+        }
+    }
+
+    public void setFieldDouble(double value, Object base, ResolvedJavaField field) {
+        long offset = resolveOffset(field);
+        if (isVolatile(field)) {
+            unsafe.putDoubleVolatile(resolveBase(base, field), offset, value);
+        } else {
+            unsafe.putDouble(resolveBase(base, field), offset, value);
+        }
+    }
+
+    public void setFieldLong(long value, Object base, ResolvedJavaField field) {
+        long offset = resolveOffset(field);
+        if (isVolatile(field)) {
+            unsafe.putDoubleVolatile(resolveBase(base, field), offset, value);
+        } else {
+            unsafe.putDouble(resolveBase(base, field), offset, value);
+        }
+    }
+
+    public byte getArrayByte(long index, Object array) {
+        checkArray(array, index);
+        return unsafe.getByte(array, Unsafe.ARRAY_BYTE_BASE_OFFSET + Unsafe.ARRAY_BYTE_INDEX_SCALE * index);
+    }
+
+    public char getArrayChar(long index, Object array) {
+        checkArray(array, index);
+        return unsafe.getChar(array, Unsafe.ARRAY_CHAR_BASE_OFFSET + Unsafe.ARRAY_CHAR_INDEX_SCALE * index);
+    }
+
+    public short getArrayShort(long index, Object array) {
+        checkArray(array, index);
+        return unsafe.getShort(array, Unsafe.ARRAY_SHORT_BASE_OFFSET + Unsafe.ARRAY_SHORT_INDEX_SCALE * index);
+    }
+
+    public int getArrayInt(long index, Object array) {
+        checkArray(array, index);
+        return unsafe.getInt(array, Unsafe.ARRAY_INT_BASE_OFFSET + Unsafe.ARRAY_INT_INDEX_SCALE * index);
+    }
+
+    public long getArrayLong(long index, Object array) {
+        checkArray(array, index);
+        return unsafe.getLong(array, Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * index);
+    }
+
+    public double getArrayDouble(long index, Object array) {
+        checkArray(array, index);
+        return unsafe.getDouble(array, Unsafe.ARRAY_DOUBLE_BASE_OFFSET + Unsafe.ARRAY_DOUBLE_INDEX_SCALE * index);
+    }
+
+    public float getArrayFloat(long index, Object array) {
+        checkArray(array, index);
+        return unsafe.getFloat(array, Unsafe.ARRAY_FLOAT_BASE_OFFSET + Unsafe.ARRAY_FLOAT_INDEX_SCALE * index);
+    }
+
+    public Object getArrayObject(long index, Object array) {
+        checkArray(array, index);
+        return unsafe.getObject(array, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * index);
+    }
+
+    public void setArrayByte(byte value, long index, Object array) {
+        checkArray(array, index);
+        if (array instanceof boolean[]) {
+            checkArrayType(array, boolean.class);
+        } else {
+            checkArrayType(array, byte.class);
+        }
+        unsafe.putByte(array, Unsafe.ARRAY_BYTE_BASE_OFFSET + Unsafe.ARRAY_BYTE_INDEX_SCALE * index, value);
+    }
+
+    public void setArrayChar(char value, long index, Object array) {
+        checkArray(array, index);
+        checkArrayType(array, char.class);
+        unsafe.putChar(array, Unsafe.ARRAY_CHAR_BASE_OFFSET + Unsafe.ARRAY_CHAR_INDEX_SCALE * index, value);
+    }
+
+    public void setArrayShort(short value, long index, Object array) {
+        checkArray(array, index);
+        checkArrayType(array, short.class);
+        unsafe.putShort(array, Unsafe.ARRAY_SHORT_BASE_OFFSET + Unsafe.ARRAY_SHORT_INDEX_SCALE * index, value);
+    }
+
+    public void setArrayInt(int value, long index, Object array) {
+        checkArray(array, index);
+        checkArrayType(array, int.class);
+        unsafe.putInt(array, Unsafe.ARRAY_INT_BASE_OFFSET + Unsafe.ARRAY_INT_INDEX_SCALE * index, value);
+    }
+
+    public void setArrayLong(long value, long index, Object array) {
+        checkArray(array, index);
+        checkArrayType(array, long.class);
+        unsafe.putLong(array, Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * index, value);
+    }
+
+    public void setArrayFloat(float value, long index, Object array) {
+        checkArray(array, index);
+        checkArrayType(array, float.class);
+        unsafe.putFloat(array, Unsafe.ARRAY_FLOAT_BASE_OFFSET + Unsafe.ARRAY_FLOAT_INDEX_SCALE * index, value);
+    }
+
+    public void setArrayDouble(double value, long index, Object array) {
+        checkArray(array, index);
+        checkArrayType(array, double.class);
+        unsafe.putDouble(array, Unsafe.ARRAY_DOUBLE_BASE_OFFSET + Unsafe.ARRAY_DOUBLE_INDEX_SCALE * index, value);
+    }
+
+    public void setArrayObject(Object value, long index, Object array) {
+        checkArray(array, index);
+        checkArrayType(array, value != null ? value.getClass() : null);
+        unsafe.putObject(array, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * index, value);
+    }
+
+    private static void nullCheck(Object value) {
+        if (value == null) {
+            throw new NullPointerException();
+        }
+    }
+
+    private void checkArrayType(Object array, Class<?> arrayType) {
+        if (arrayType == null) {
+            return;
+        }
+        ResolvedJavaType type = metaProvider.getResolvedJavaType(array.getClass()).componentType();
+        if (!type.toJava().isAssignableFrom(arrayType)) {
+            throw new ArrayStoreException(arrayType.getName());
+        }
+    }
+
+    private void checkArray(Object array, long index) {
+        nullCheck(array);
+        ResolvedJavaType type = metaProvider.getResolvedJavaType(array.getClass());
+        if (!type.isArrayClass()) {
+            throw new ArrayStoreException(array.getClass().getName());
+        }
+        if (index < 0 || index >= arrayLength(array)) {
+            throw new ArrayIndexOutOfBoundsException((int) index);
+        }
+    }
+
+    private static int arrayLength(Object array) {
+        assert array != null;
+        return Array.getLength(array);
+    }
+
+    private static boolean isVolatile(ResolvedJavaField field) {
+        return Modifier.isVolatile(field.accessFlags());
+    }
+
+    private static long resolveOffset(ResolvedJavaField field) {
+        return ((HotSpotResolvedJavaField) field).offset();
+    }
+
+    private static Object resolveBase(Object base, ResolvedJavaField field) {
+        Object accessorBase = base;
+        if (accessorBase == null) {
+            accessorBase = field.holder().toJava();
+        }
+        return accessorBase;
+    }
+
+    private static Unsafe loadUnsafe() {
+        try {
+            return Unsafe.getUnsafe();
+        } catch (SecurityException e) {
+        }
+        try {
+            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
+            theUnsafeInstance.setAccessible(true);
+            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
+        } catch (Exception e) {
+            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Jul 05 16:54:45 2012 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.hotspot;
 
-import com.oracle.graal.api.meta.*;
-
 /**
  * Used to communicate configuration details, runtime offsets, etc. to graal upon compileMethod.
  */
@@ -46,22 +44,69 @@
     // offsets, ...
     public int vmPageSize;
     public int stackShadowPages;
+
+    /**
+     * The offset of the mark word in an object's header.
+     */
+    public int markOffset;
+
+    /**
+     * The offset of the hub/klassOop word in an object's header.
+     */
     public int hubOffset;
+
+    /**
+     * The offset of an the array length in an array's header.
+     */
+    public int arrayLengthOffset;
+
+    /**
+     * The offset of the _super_check_offset field in a Klass.
+     */
     public int superCheckOffsetOffset;
+
+    /**
+     * The offset of the _secondary_super_cache field in a Klass.
+     */
     public int secondarySuperCacheOffset;
+
+    /**
+     * The offset of the _secondary_supers field in a Klass.
+     */
     public int secondarySupersOffset;
-    public int arrayLengthOffset;
+
+    /**
+     * The offset of the _init_state field in an instanceKlass.
+     */
     public int klassStateOffset;
+
+    /**
+     * The value of instanceKlass::fully_initialized.
+     */
     public int klassStateFullyInitialized;
-    public int[] arrayOffsets;
+
+    /**
+     * The value of objArrayKlass::element_klass_offset().
+     */
     public int arrayClassElementOffset;
+
+    /**
+     * The value of JavaThread::tlab_top_offset().
+     */
     public int threadTlabTopOffset;
+
+    /**
+     * The value of JavaThread::tlab_end_offset().
+     */
     public int threadTlabEndOffset;
+
     public int threadObjectOffset;
+
     public int instanceHeaderPrototypeOffset;
+
     public int threadExceptionOopOffset;
     public int threadExceptionPcOffset;
-    public int threadMultiNewArrayStorage;
+    public int threadMultiNewArrayStorageOffset;
     public long cardtableStartAddress;
     public int cardtableShift;
     public long safepointPollingAddress;
@@ -110,8 +155,4 @@
         assert codeEntryAlignment > 0;
         assert stackShadowPages > 0;
     }
-
-    public int getArrayOffset(Kind kind) {
-        return arrayOffsets[kind.ordinal()];
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu Jul 05 16:54:45 2012 +0200
@@ -105,8 +105,6 @@
 
     String disassembleNative(byte[] code, long address);
 
-    String disassembleJava(HotSpotResolvedJavaMethod method);
-
     StackTraceElement JavaMethod_toStackTraceElement(HotSpotResolvedJavaMethod method, int bci);
 
     Object executeCompiledMethod(HotSpotCompiledMethod method, Object arg1, Object arg2, Object arg3);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Jul 05 16:54:45 2012 +0200
@@ -150,9 +150,6 @@
     public native String disassembleNative(byte[] code, long address);
 
     @Override
-    public native String disassembleJava(HotSpotResolvedJavaMethod method);
-
-    @Override
     public native StackTraceElement JavaMethod_toStackTraceElement(HotSpotResolvedJavaMethod method, int bci);
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Jul 05 16:54:45 2012 +0200
@@ -48,7 +48,7 @@
  */
 public class VMToCompilerImpl implements VMToCompiler {
 
-    private final HotSpotGraalRuntime compiler;
+    private final HotSpotGraalRuntime graalRuntime;
     private IntrinsifyArrayCopyPhase intrinsifyArrayCopy;
 
     public final HotSpotTypePrimitive typeBoolean;
@@ -68,7 +68,7 @@
     private PrintStream log = System.out;
 
     public VMToCompilerImpl(HotSpotGraalRuntime compiler) {
-        this.compiler = compiler;
+        this.graalRuntime = compiler;
 
         typeBoolean = new HotSpotTypePrimitive(Kind.Boolean);
         typeChar = new HotSpotTypePrimitive(Kind.Char);
@@ -105,9 +105,10 @@
             Debug.setConfig(hotspotDebugConfig);
         }
         // Install intrinsics.
-        final HotSpotRuntime runtime = (HotSpotRuntime) compiler.getCompiler().runtime;
+        GraalCompiler compiler = graalRuntime.getCompiler();
+        final HotSpotRuntime runtime = (HotSpotRuntime) compiler.runtime;
         if (GraalOptions.Intrinsify) {
-            Debug.scope("InstallSnippets", new DebugDumpScope("InstallSnippets"), new Runnable() {
+            Debug.scope("InstallSnippets", new Object[] {new DebugDumpScope("InstallSnippets"), compiler}, new Runnable() {
 
                 @Override
                 public void run() {
@@ -214,16 +215,16 @@
         CompilationStatistics.clear("bootstrap");
 
         TTY.println(" in %d ms", System.currentTimeMillis() - startTime);
-        if (compiler.getCache() != null) {
-            compiler.getCache().clear();
+        if (graalRuntime.getCache() != null) {
+            graalRuntime.getCache().clear();
         }
         System.gc();
         CompilationStatistics.clear("bootstrap2");
-        MethodEntryCounters.printCounters(compiler);
+        MethodEntryCounters.printCounters(graalRuntime);
     }
 
     private void enqueue(Method m) throws Throwable {
-        JavaMethod javaMethod = compiler.getRuntime().getResolvedJavaMethod(m);
+        JavaMethod javaMethod = graalRuntime.getRuntime().getResolvedJavaMethod(m);
         assert !Modifier.isAbstract(((HotSpotResolvedJavaMethod) javaMethod).accessFlags()) && !Modifier.isNative(((HotSpotResolvedJavaMethod) javaMethod).accessFlags()) : javaMethod;
         compileMethod((HotSpotResolvedJavaMethod) javaMethod, 0, false, 10);
     }
@@ -285,7 +286,7 @@
             }
         }
         CompilationStatistics.clear("final");
-        MethodEntryCounters.printCounters(compiler);
+        MethodEntryCounters.printCounters(graalRuntime);
         HotSpotXirGenerator.printCounters(TTY.out().out());
         CheckCastSnippets.printCounters(TTY.out().out());
     }
@@ -374,7 +375,7 @@
 
             final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(method);
             int id = compileTaskIds.incrementAndGet();
-            CompilationTask task = CompilationTask.create(compiler, createPhasePlan(optimisticOpts), optimisticOpts, method, id, priority);
+            CompilationTask task = CompilationTask.create(graalRuntime, createPhasePlan(optimisticOpts), optimisticOpts, method, id, priority);
             if (blocking) {
                 task.runCompilation();
             } else {
@@ -483,7 +484,7 @@
 
     public PhasePlan createPhasePlan(OptimisticOptimizations optimisticOpts) {
         PhasePlan phasePlan = new PhasePlan();
-        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime(), GraphBuilderConfiguration.getDefault(), optimisticOpts);
+        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(graalRuntime.getRuntime(), GraphBuilderConfiguration.getDefault(), optimisticOpts);
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
         if (GraalOptions.Intrinsify) {
             phasePlan.addPhase(PhasePosition.HIGH_LEVEL, intrinsifyArrayCopy);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java	Thu Jul 05 16:54:45 2012 +0200
@@ -54,7 +54,11 @@
     private ConstantPool constantPool;
     private boolean isInitialized;
     private ResolvedJavaType arrayOfType;
-    private long prototypeHeader;
+
+    /**
+     * Initial value for the mark word in a new object of this type.
+     */
+    private long initialMarkWord;
 
     private HotSpotResolvedJavaType() {
         throw new GraalInternalError(HotSpotResolvedJavaType.class + " should only be created from C++ code");
@@ -285,7 +289,7 @@
         return superCheckOffset;
     }
 
-    public long prototypeHeader() {
-        return prototypeHeader;
+    public long initialMarkWord() {
+        return initialMarkWord;
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Jul 05 16:54:45 2012 +0200
@@ -28,10 +28,13 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CompilationResult.*;
-import com.oracle.graal.api.code.CodeUtil.*;
+import com.oracle.graal.api.code.CodeUtil.RefMapFormatter;
+import com.oracle.graal.api.code.CompilationResult.Call;
+import com.oracle.graal.api.code.CompilationResult.DataPatch;
+import com.oracle.graal.api.code.CompilationResult.Mark;
+import com.oracle.graal.api.code.CompilationResult.Safepoint;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.JavaType.*;
+import com.oracle.graal.api.meta.JavaType.Representation;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
@@ -57,7 +60,7 @@
     private final HotSpotRegisterConfig globalStubRegConfig;
     private final HotSpotGraalRuntime compiler;
     private CheckCastSnippets.Templates checkcastSnippets;
-    private NewInstanceSnippets.Templates newInstanceSnippets;
+    private NewObjectSnippets.Templates newObjectSnippets;
 
     public HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime compiler) {
         this.config = config;
@@ -73,9 +76,9 @@
         installer.install(UnsafeSnippets.class);
         installer.install(ArrayCopySnippets.class);
         installer.install(CheckCastSnippets.class);
-        installer.install(NewInstanceSnippets.class);
+        installer.install(NewObjectSnippets.class);
         checkcastSnippets = new CheckCastSnippets.Templates(this);
-        newInstanceSnippets = new NewInstanceSnippets.Templates(this, config.useTLAB);
+        newObjectSnippets = new NewObjectSnippets.Templates(this, compiler.getTarget(), config.useTLAB);
     }
 
 
@@ -177,11 +180,6 @@
     }
 
     @Override
-    public String disassemble(ResolvedJavaMethod method) {
-        return compiler.getCompilerToVM().disassembleJava((HotSpotResolvedJavaMethod) method);
-    }
-
-    @Override
     public ResolvedJavaType getResolvedJavaType(Kind kind) {
         return (ResolvedJavaType) compiler.getCompilerToVM().getType(kind.toJavaClass());
     }
@@ -373,12 +371,18 @@
             }
         } else if (n instanceof NewInstanceNode) {
             if (shouldLower(graph, GraalOptions.HIRLowerNewInstance)) {
-                newInstanceSnippets.lower((NewInstanceNode) n, tool);
+                newObjectSnippets.lower((NewInstanceNode) n, tool);
+            }
+        } else if (n instanceof NewArrayNode) {
+            if (shouldLower(graph, GraalOptions.HIRLowerNewArray)) {
+                newObjectSnippets.lower((NewArrayNode) n, tool);
             }
         } else if (n instanceof TLABAllocateNode) {
-            newInstanceSnippets.lower((TLABAllocateNode) n, tool);
-        } else if (n instanceof InitializeNode) {
-            newInstanceSnippets.lower((InitializeNode) n, tool);
+            newObjectSnippets.lower((TLABAllocateNode) n, tool);
+        } else if (n instanceof InitializeObjectNode) {
+            newObjectSnippets.lower((InitializeObjectNode) n, tool);
+        } else if (n instanceof InitializeArrayNode) {
+            newObjectSnippets.lower((InitializeArrayNode) n, tool);
         } else {
             assert false : "Node implementing Lowerable not handled: " + n;
         }
@@ -395,8 +399,8 @@
         return false;
     }
 
-    private IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) {
-        return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), index, graph, true);
+    private static IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) {
+        return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, elementKind.arrayBaseOffset(), index, graph, true);
     }
 
     private SafeReadNode safeReadArrayLength(ValueNode array, long leafGraphId) {
@@ -528,6 +532,7 @@
 
     @Override
     public int convertDeoptAction(DeoptimizationAction action) {
+        // This must be kept in sync with the DeoptAction enum defined in deoptimization.hpp
         switch(action) {
             case None: return 0;
             case RecompileIfTooManyDeopts: return 1;
@@ -540,6 +545,7 @@
 
     @Override
     public int convertDeoptReason(DeoptimizationReason reason) {
+        // This must be kept in sync with the DeoptReason enum defined in deoptimization.hpp
         switch(reason) {
             case None: return 0;
             case NullCheckException: return 1;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java	Thu Jul 05 16:54:45 2012 +0200
@@ -315,7 +315,7 @@
             asm.bindInline(resume);
 
             asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false);
-            asm.pstore(target.wordKind, result, temp1, false);
+            asm.pstore(target.wordKind, result, asm.i(config.markOffset), temp1, false);
             asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory
             asm.pstore(Kind.Object, result, asm.i(config.hubOffset), temp1o, false);
 
@@ -378,7 +378,7 @@
 
             final int aligning = target.wordSize;
             final int arrayLengthOffset = target.wordSize * 2;
-            final int arrayElementOffset = config.getArrayOffset(kind);
+            final int arrayElementOffset = kind.arrayBaseOffset();
 
             // Calculate aligned size
             asm.mov(size, length);
@@ -401,7 +401,7 @@
 
             // Now the new object is in result, store mark word and klass
             asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false);
-            asm.pstore(target.wordKind, result, temp1, false);
+            asm.pstore(target.wordKind, result, asm.i(config.markOffset), temp1, false);
             asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory
             asm.pstore(Kind.Object, result, asm.i(config.hubOffset), temp1o, false);
 
@@ -447,7 +447,7 @@
             XirOperand rank = asm.createRegisterTemp("rank", Kind.Int, AMD64.rbx);
             XirOperand sizes = asm.createRegisterTemp("sizes", Kind.Long, AMD64.rcx);
             XirOperand thread = asm.createRegisterTemp("thread", Kind.Long, AMD64.r15);
-            asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorage));
+            asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorageOffset));
             for (int i = 0; i < dimensions; i++) {
                 XirParameter length = asm.createInputParameter("length" + i, Kind.Int, true);
                 asm.pstore(Kind.Int, sizes, asm.i(i * target.sizeInBytes(Kind.Int)), length, false);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CastFromHub.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CastFromHub.java	Thu Jul 05 16:54:45 2012 +0200
@@ -32,7 +32,7 @@
 import com.oracle.graal.nodes.type.*;
 
 /**
- * This node is used by the {@link NewInstanceSnippets} to give a formatted new instance its exact type.
+ * This node is used by the {@link NewObjectSnippets} to give a formatted new instance or object its exact type.
  */
 public final class CastFromHub extends FloatingNode implements Canonicalizable {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Initializes the header and body of an uninitialized array cell.
+ * This node calls out to a stub to do both the allocation and formatting
+ * if the memory address it is given is zero/null (e.g. due to
+ * {@linkplain TLABAllocateNode TLAB allocation} failing).
+ */
+public final class InitializeArrayNode extends FixedWithNextNode implements Lowerable {
+
+    @Input private final ValueNode memory;
+    @Input private final ValueNode length;
+    @Input private final ValueNode size;
+    private final ResolvedJavaType type;
+
+    public InitializeArrayNode(ValueNode memory, ValueNode length, ValueNode size, ResolvedJavaType type) {
+        super(StampFactory.exactNonNull(type));
+        this.memory = memory;
+        this.type = type;
+        this.length = length;
+        this.size = size;
+    }
+
+    public ValueNode memory() {
+        return memory;
+    }
+
+    public ValueNode length() {
+        return length;
+    }
+
+    public ValueNode size() {
+        return size;
+    }
+
+    public ResolvedJavaType type() {
+        return type;
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static Object initialize(Object memory, int length, int size, @ConstantNodeParameter ResolvedJavaType type) {
+        throw new UnsupportedOperationException();
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.nodes;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-/**
- * Initializes the header and body of an uninitialized object cell.
- * This node calls out to a stub to do both the allocation and formatting
- * if the memory address it is given is zero/null (e.g. due to
- * {@linkplain TLABAllocateNode TLAB allocation} failing).
- */
-public final class InitializeNode extends FixedWithNextNode implements Lowerable {
-
-    @Input private final ValueNode memory;
-    private final ResolvedJavaType type;
-
-    public InitializeNode(ValueNode memory, ResolvedJavaType type) {
-        super(StampFactory.exactNonNull(type));
-        this.memory = memory;
-        this.type = type;
-    }
-
-    public ValueNode memory() {
-        return memory;
-    }
-
-    public ResolvedJavaType type() {
-        return type;
-    }
-
-    @Override
-    public void lower(LoweringTool tool) {
-        tool.getRuntime().lower(this, tool);
-    }
-
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static Object initialize(Object memory, @ConstantNodeParameter ResolvedJavaType type) {
-        throw new UnsupportedOperationException();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Initializes the header and body of an uninitialized object cell.
+ * This node calls out to a stub to do both the allocation and formatting
+ * if the memory address it is given is zero/null (e.g. due to
+ * {@linkplain TLABAllocateNode TLAB allocation} failing).
+ */
+public final class InitializeObjectNode extends FixedWithNextNode implements Lowerable {
+
+    @Input private final ValueNode memory;
+    private final ResolvedJavaType type;
+
+    public InitializeObjectNode(ValueNode memory, ResolvedJavaType type) {
+        super(StampFactory.exactNonNull(type));
+        this.memory = memory;
+        this.type = type;
+    }
+
+    public ValueNode memory() {
+        return memory;
+    }
+
+    public ResolvedJavaType type() {
+        return type;
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import static com.oracle.graal.hotspot.target.amd64.AMD64NewArrayStubCallOp.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.target.amd64.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Node implementing a call to HotSpot's {@code new_[object|type]_array} stub.
+ *
+ * @see AMD64NewArrayStubCallOp
+ */
+public class NewArrayStubCall extends FixedWithNextNode implements LIRGenLowerable {
+
+    private static final Stamp defaultStamp = StampFactory.objectNonNull();
+
+    @Input private final ValueNode hub;
+    @Input private final ValueNode length;
+    private final boolean isObjectArray;
+
+    public NewArrayStubCall(boolean isObjectArray, ValueNode hub, ValueNode length) {
+        super(defaultStamp);
+        this.isObjectArray = isObjectArray;
+        this.hub = hub;
+        this.length = length;
+    }
+
+    @Override
+    public boolean inferStamp() {
+        if (stamp() == defaultStamp && hub.isConstant()) {
+            HotSpotKlassOop klassOop = (HotSpotKlassOop) this.hub.asConstant().asObject();
+            updateStamp(StampFactory.exactNonNull(klassOop.type));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void generate(LIRGenerator gen) {
+        RegisterValue hubFixed = HUB.asValue(Kind.Object);
+        RegisterValue lengthFixed = LENGTH.asValue(Kind.Int);
+        RegisterValue resultFixed = RESULT.asValue(Kind.Object);
+        gen.emitMove(gen.operand(length), lengthFixed);
+        gen.emitMove(gen.operand(hub), hubFixed);
+        LIRFrameState info = gen.state();
+        gen.append(new AMD64NewArrayStubCallOp(isObjectArray, resultFixed, hubFixed, lengthFixed, info));
+        Variable result = gen.emitMove(resultFixed);
+        gen.setResult(this, result);
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static Object call(@ConstantNodeParameter boolean isObjectArray, Object hub, int length) {
+        throw new UnsupportedOperationException();
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Thu Jul 05 16:54:45 2012 +0200
@@ -22,15 +22,17 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import static com.oracle.graal.hotspot.target.amd64.AMD64NewInstanceStubCallOp.*;
+
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.target.*;
+import com.oracle.graal.hotspot.target.amd64.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.max.asm.target.amd64.*;
 
 /**
  * Node implementing a call to HotSpot's {@code new_instance} stub.
@@ -60,11 +62,12 @@
 
     @Override
     public void generate(LIRGenerator gen) {
-        Variable result = gen.newVariable(Kind.Object);
-        gen.emitMove(gen.operand(hub), AMD64.rdx.asValue(Kind.Object));
+        RegisterValue hubFixed = HUB.asValue(Kind.Object);
+        RegisterValue resultFixed = RESULT.asValue(Kind.Object);
+        gen.emitMove(gen.operand(hub), hubFixed);
         LIRFrameState info = gen.state();
-        AMD64NewInstanceStubCallOp op = new AMD64NewInstanceStubCallOp(result, AMD64.rdx.asValue(Kind.Object), info);
-        gen.append(op);
+        gen.append(new AMD64NewInstanceStubCallOp(resultFixed, hubFixed, info));
+        Variable result = gen.emitMove(resultFixed);
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -35,27 +37,61 @@
 public final class TLABAllocateNode extends FixedWithNextNode implements Lowerable {
 
     private final int size;
+    @Input private ValueNode sizeNode;
 
     public TLABAllocateNode(int size, Kind wordKind) {
         super(StampFactory.forWord(wordKind, true));
         this.size = size;
+        this.sizeNode = null;
+    }
+
+    public TLABAllocateNode(Kind wordKind, ValueNode size) {
+        super(StampFactory.forWord(wordKind, true));
+        this.size = -1;
+        this.sizeNode = size;
     }
 
-    public int size() {
+    public boolean isSizeConstant() {
+        return sizeNode == null;
+    }
+
+    public int constantSize() {
+        assert isSizeConstant();
         return size;
     }
 
+    public ValueNode variableSize() {
+        assert !isSizeConstant();
+        return sizeNode;
+    }
+
     @Override
     public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> debugProperties = super.getDebugProperties();
+        debugProperties.put("size", String.valueOf(size));
+        return debugProperties;
+    }
+
     /**
      * @return null if allocation fails
      */
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static Word allocate(@ConstantNodeParameter int size, @ConstantNodeParameter Kind wordKind) {
+    public static Word allocateConstantSize(@ConstantNodeParameter int size, @ConstantNodeParameter Kind wordKind) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @return null if allocation fails
+     */
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static Word allocateVariableSize(@ConstantNodeParameter Kind wordKind, int size) {
         throw new UnsupportedOperationException();
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Thu Jul 05 16:54:45 2012 +0200
@@ -22,9 +22,13 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import static com.oracle.graal.hotspot.target.amd64.AMD64VerifyOopStubCallOp.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.hotspot.target.*;
+import com.oracle.graal.hotspot.target.amd64.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
@@ -45,9 +49,10 @@
 
     @Override
     public void generate(LIRGenerator gen) {
+        RegisterValue objectFixed = OBJECT.asValue(Kind.Object);
+        gen.emitMove(gen.operand(object), objectFixed);
         LIRFrameState info = gen.state();
-        AMD64VerifyOopStubCallOp op = new AMD64VerifyOopStubCallOp(gen.operand(object), info);
-        gen.append(op);
+        gen.append(new AMD64VerifyOopStubCallOp(gen.operand(object), info));
     }
 
     @SuppressWarnings("unused")
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Thu Jul 05 16:54:45 2012 +0200
@@ -81,7 +81,7 @@
         long srcOffset = srcPos * arrayIndexScale(baseKind);
         long destOffset = destPos * arrayIndexScale(baseKind);
         if (src == dest && srcPos < destPos) { // bad aliased case
-            for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i--) {
+            for (long i = byteLength - arrayIndexScale(Kind.Byte); i >= byteLength - nonVectorBytes; i -= arrayIndexScale(Kind.Byte)) {
                 Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
                 UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
             }
@@ -91,7 +91,7 @@
                 UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
             }
         } else {
-            for (long i = 0; i < nonVectorBytes; i++) {
+            for (long i = 0; i < nonVectorBytes; i += arrayIndexScale(Kind.Byte)) {
                 Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
                 UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
             }
@@ -117,9 +117,9 @@
         long srcOffset = srcPos * arrayIndexScale(baseKind);
         long destOffset = destPos * arrayIndexScale(baseKind);
         if (src == dest && srcPos < destPos) { // bad aliased case
-            for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i--) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = byteLength - arrayIndexScale(Kind.Char); i >= byteLength - nonVectorBytes; i -= arrayIndexScale(Kind.Char)) {
+                Character a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Char);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.charValue(), Kind.Char);
             }
             long vectorLength = byteLength - nonVectorBytes;
             for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
@@ -127,9 +127,9 @@
                 UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
             }
         } else {
-            for (long i = 0; i < nonVectorBytes; i++) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = 0; i < nonVectorBytes; i += arrayIndexScale(Kind.Char)) {
+                Character a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Char);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.charValue(), Kind.Char);
             }
             for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) {
                 Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
@@ -153,9 +153,9 @@
         long srcOffset = srcPos * arrayIndexScale(baseKind);
         long destOffset = destPos * arrayIndexScale(baseKind);
         if (src == dest && srcPos < destPos) { // bad aliased case
-            for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i--) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = byteLength - arrayIndexScale(Kind.Short); i >= byteLength - nonVectorBytes; i -= arrayIndexScale(Kind.Short)) {
+                Short a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Short);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.shortValue(), Kind.Short);
             }
             long vectorLength = byteLength - nonVectorBytes;
             for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
@@ -163,9 +163,9 @@
                 UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
             }
         } else {
-            for (long i = 0; i < nonVectorBytes; i++) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = 0; i < nonVectorBytes; i += arrayIndexScale(Kind.Short)) {
+                Short a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Short);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.shortValue(), Kind.Short);
             }
             for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) {
                 Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
@@ -189,9 +189,9 @@
         long srcOffset = srcPos * arrayIndexScale(baseKind);
         long destOffset = destPos * arrayIndexScale(baseKind);
         if (src == dest && srcPos < destPos) { // bad aliased case
-            for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i--) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = byteLength - arrayIndexScale(Kind.Int); i >= byteLength - nonVectorBytes; i -= arrayIndexScale(Kind.Int)) {
+                Integer a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Int);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.intValue(), Kind.Int);
             }
             long vectorLength = byteLength - nonVectorBytes;
             for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
@@ -199,9 +199,9 @@
                 UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
             }
         } else {
-            for (long i = 0; i < nonVectorBytes; i++) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = 0; i < nonVectorBytes; i += arrayIndexScale(Kind.Int)) {
+                Integer a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Int);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.intValue(), Kind.Int);
             }
             for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) {
                 Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
@@ -225,9 +225,9 @@
         long srcOffset = srcPos * arrayIndexScale(baseKind);
         long destOffset = destPos * arrayIndexScale(baseKind);
         if (src == dest && srcPos < destPos) { // bad aliased case
-            for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i--) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = byteLength - arrayIndexScale(Kind.Float); i >= byteLength - nonVectorBytes; i -= arrayIndexScale(Kind.Float)) {
+                Float a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Float);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.floatValue(), Kind.Float);
             }
             long vectorLength = byteLength - nonVectorBytes;
             for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
@@ -235,9 +235,9 @@
                 UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
             }
         } else {
-            for (long i = 0; i < nonVectorBytes; i++) {
-                Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte);
-                UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte);
+            for (long i = 0; i < nonVectorBytes; i += arrayIndexScale(Kind.Float)) {
+                Float a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Float);
+                UnsafeStoreNode.store(dest, header, i + destOffset, a.floatValue(), Kind.Float);
             }
             for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) {
                 Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
@@ -308,13 +308,19 @@
             throw new IndexOutOfBoundsException();
         }
         final int scale = arrayIndexScale(Kind.Object);
+        int header = arrayBaseOffset(Kind.Object);
         if (src == dest && srcPos < destPos) { // bad aliased case
-            copyObjectsDown(src, srcPos * scale, dest, destPos * scale, length);
+            for (long i = (length - 1) * scale; i >= 0; i -= scale) {
+                Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object);
+                DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a);
+            }
         } else {
-            copyObjectsUp(src, srcPos * scale, dest, destPos * scale, length);
+            for (long i = 0; i < length * scale; i += scale) {
+                Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object);
+                DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a);
+            }
         }
         if (length > 0) {
-            int header = arrayBaseOffset(Kind.Object);
             int cardShift = cardTableShift();
             long cardStart = cardTableStart();
             long dstAddr = GetObjectAddressNode.get(dest);
@@ -327,28 +333,6 @@
         }
     }
 
-    // Does NOT perform store checks
-    @Snippet
-    public static void copyObjectsDown(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        int header = arrayBaseOffset(Kind.Object);
-        final int scale = arrayIndexScale(Kind.Object);
-        for (long i = (length - 1) * scale; i >= 0; i -= scale) {
-            Object a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Object);
-            DirectObjectStoreNode.store(dest, header, i + destOffset, a);
-        }
-    }
-
-    // Does NOT perform store checks
-    @Snippet
-    public static void copyObjectsUp(Object src, long srcOffset, Object dest, long destOffset, int length)  {
-        int header = arrayBaseOffset(Kind.Object);
-        final int scale = arrayIndexScale(Kind.Object);
-        for (long i = 0; i < length * scale; i += scale) {
-            Object a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Object);
-            DirectObjectStoreNode.store(dest, header, i + destOffset, a);
-        }
-    }
-
     @Fold
     static int arrayBaseOffset(Kind elementKind) {
         return elementKind.arrayBaseOffset();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Thu Jul 05 16:54:45 2012 +0200
@@ -174,7 +174,7 @@
 
         for (int i = 0; i < secondarySupers.length; i++) {
             if (t == loadNonNullObjectElement(secondarySupers, i)) {
-                DirectObjectStoreNode.store(s, secondarySuperCacheOffset(), 0, t);
+                DirectObjectStoreNode.storeObject(s, secondarySuperCacheOffset(), 0, t);
                 secondariesHit.inc();
                 return true;
             }
@@ -214,7 +214,7 @@
         Object[] secondarySupers = UnsafeCastNode.cast(UnsafeLoadNode.loadObject(s, 0, secondarySupersOffset(), true), Object[].class);
         for (int i = 0; i < secondarySupers.length; i++) {
             if (t == loadNonNullObjectElement(secondarySupers, i)) {
-                DirectObjectStoreNode.store(s, secondarySuperCacheOffset(), 0, t);
+                DirectObjectStoreNode.storeObject(s, secondarySuperCacheOffset(), 0, t);
                 secondariesHit.inc();
                 return true;
             }
@@ -264,7 +264,7 @@
          */
         void inc() {
             if (ENABLED) {
-                DirectObjectStoreNode.store(this, countOffset(), 0, count + 1);
+                DirectObjectStoreNode.storeLong(this, countOffset(), 0, count + 1);
             }
         }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectObjectStoreNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectObjectStoreNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -26,6 +26,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.snippets.*;
 
 /**
  * A special purpose store node that differs from {@link UnsafeStoreNode} in that
@@ -47,13 +48,25 @@
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object obj, @ConstantNodeParameter int displacement, long offset, Object value) {
+    public static void storeObject(Object obj, @ConstantNodeParameter int displacement, long offset, Object value) {
         throw new UnsupportedOperationException();
     }
 
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static void store(Object obj, @ConstantNodeParameter int displacement, long offset, long value) {
+    public static void storeLong(Object obj, @ConstantNodeParameter int displacement, long offset, long value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static void storeWord(Object obj, @ConstantNodeParameter int displacement, long offset, Word value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static void storeInt(Object obj, @ConstantNodeParameter int displacement, long offset, int value) {
         throw new UnsupportedOperationException();
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java	Thu Jul 05 16:54:00 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,229 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.snippets;
-
-import static com.oracle.graal.hotspot.nodes.CastFromHub.*;
-import static com.oracle.graal.hotspot.nodes.RegisterNode.*;
-import static com.oracle.graal.hotspot.snippets.DirectObjectStoreNode.*;
-import static com.oracle.graal.nodes.extended.UnsafeLoadNode.*;
-import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*;
-import static com.oracle.graal.snippets.nodes.ExplodeLoopNode.*;
-import static com.oracle.max.asm.target.amd64.AMD64.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.snippets.*;
-import com.oracle.graal.snippets.Snippet.ConstantParameter;
-import com.oracle.graal.snippets.Snippet.Fold;
-import com.oracle.graal.snippets.Snippet.Parameter;
-import com.oracle.graal.snippets.SnippetTemplate.Arguments;
-import com.oracle.graal.snippets.SnippetTemplate.Cache;
-import com.oracle.graal.snippets.SnippetTemplate.Key;
-
-/**
- * Snippets used for implementing NEW.
- */
-public class NewInstanceSnippets implements SnippetsInterface {
-
-    @Snippet
-    public static Word allocate(@ConstantParameter("size") int size) {
-        Word thread = asWord(register(r15, wordKind()));
-        Word top = loadWord(thread, threadTlabTopOffset());
-        Word end = loadWord(thread, threadTlabEndOffset());
-        Word newTop = top.plus(size);
-        if (newTop.belowOrEqual(end)) {
-            store(thread, 0, threadTlabTopOffset(), newTop);
-            return top;
-        }
-        return Word.zero();
-    }
-
-    @Snippet
-    public static Object initialize(
-                    @Parameter("memory") Word memory,
-                    @Parameter("hub") Object hub,
-                    @Parameter("prototypeHeader") Word headerPrototype,
-                    @ConstantParameter("size") int size) {
-
-        if (memory == Word.zero()) {
-            return NewInstanceStubCall.call(hub);
-        }
-        formatObject(hub, size, memory, headerPrototype);
-        Object instance = memory.toObject();
-        return castFromHub(verifyOop(instance), hub);
-    }
-
-    private static Object verifyOop(Object object) {
-        if (verifyOops()) {
-            VerifyOopStubCall.call(object);
-        }
-        return object;
-    }
-
-    private static Word asWord(Object object) {
-        return Word.fromObject(object);
-    }
-
-    private static Word loadWord(Word address, int offset) {
-        Object value = loadObject(address, 0, offset, true);
-        return asWord(value);
-    }
-
-    /**
-     * Maximum size of an object whose body is initialized by a sequence of
-     * zero-stores to its fields. Larger objects have their bodies initialized
-     * in a loop.
-     */
-    private static final int MAX_UNROLLED_OBJECT_INITIALIZATION_SIZE = 10 * wordSize();
-
-    /**
-     * Formats some allocated memory with an object header zeroes out the rest.
-     */
-    private static void formatObject(Object hub, int size, Word memory, Word headerPrototype) {
-        store(memory, 0, 0, headerPrototype);
-        store(memory, 0, hubOffset(), hub);
-        if (size <= MAX_UNROLLED_OBJECT_INITIALIZATION_SIZE) {
-            explodeLoop();
-            for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) {
-                store(memory, 0, offset, 0);
-            }
-        } else {
-            for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) {
-                store(memory, 0, offset, 0);
-            }
-        }
-    }
-
-    @Fold
-    private static boolean verifyOops() {
-        return HotSpotGraalRuntime.getInstance().getConfig().verifyOops;
-    }
-
-    @Fold
-    private static int threadTlabTopOffset() {
-        return HotSpotGraalRuntime.getInstance().getConfig().threadTlabTopOffset;
-    }
-
-    @Fold
-    private static int threadTlabEndOffset() {
-        return HotSpotGraalRuntime.getInstance().getConfig().threadTlabEndOffset;
-    }
-
-    @Fold
-    private static Kind wordKind() {
-        return HotSpotGraalRuntime.getInstance().getTarget().wordKind;
-    }
-
-    @Fold
-    private static int wordSize() {
-        return HotSpotGraalRuntime.getInstance().getTarget().wordSize;
-    }
-
-    @Fold
-    private static int hubOffset() {
-        return HotSpotGraalRuntime.getInstance().getConfig().hubOffset;
-    }
-
-    public static class Templates {
-
-        private final Cache cache;
-        private final ResolvedJavaMethod allocate;
-        private final ResolvedJavaMethod initialize;
-        private final CodeCacheProvider runtime;
-        private final boolean useTLAB;
-
-        public Templates(CodeCacheProvider runtime, boolean useTLAB) {
-            this.runtime = runtime;
-            this.cache = new Cache(runtime);
-            this.useTLAB = useTLAB;
-            try {
-                allocate = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("allocate", int.class));
-                initialize = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("initialize", Word.class, Object.class, Word.class, int.class));
-            } catch (NoSuchMethodException e) {
-                throw new GraalInternalError(e);
-            }
-        }
-
-        /**
-         * Lowers a {@link NewInstanceNode}.
-         */
-        @SuppressWarnings("unused")
-        public void lower(NewInstanceNode newInstanceNode, LoweringTool tool) {
-            StructuredGraph graph = (StructuredGraph) newInstanceNode.graph();
-            HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) newInstanceNode.instanceClass();
-            HotSpotKlassOop hub = type.klassOop();
-            int size = type.instanceSize();
-            assert (size % wordSize()) == 0;
-            assert size >= 0;
-
-            ValueNode memory;
-            if (!useTLAB) {
-                memory = ConstantNode.forObject(null, runtime, graph);
-            } else {
-                TLABAllocateNode tlabAllocateNode = graph.add(new TLABAllocateNode(size, wordKind()));
-                graph.addBeforeFixed(newInstanceNode, tlabAllocateNode);
-                memory = tlabAllocateNode;
-            }
-            InitializeNode initializeNode = graph.add(new InitializeNode(memory, type));
-            graph.replaceFixedWithFixed(newInstanceNode, initializeNode);
-        }
-
-        @SuppressWarnings("unused")
-        public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) {
-            StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph();
-            int size = tlabAllocateNode.size();
-            assert (size % wordSize()) == 0;
-            assert size >= 0;
-            Key key = new Key(allocate).add("size", size);
-            Arguments arguments = new Arguments();
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments);
-            template.instantiate(runtime, tlabAllocateNode, tlabAllocateNode, arguments);
-        }
-
-        @SuppressWarnings("unused")
-        public void lower(InitializeNode initializeNode, LoweringTool tool) {
-            StructuredGraph graph = (StructuredGraph) initializeNode.graph();
-            HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) initializeNode.type();
-            HotSpotKlassOop hub = type.klassOop();
-            int size = type.instanceSize();
-            assert (size % wordSize()) == 0;
-            assert size >= 0;
-            Key key = new Key(initialize).add("size", size);
-            ValueNode memory = initializeNode.memory();
-            //assert memory instanceof AllocateNode || memory instanceof ConstantNode : memory;
-            Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeHeader", type.prototypeHeader());
-            SnippetTemplate template = cache.get(key);
-            Debug.log("Lowering initialize in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments);
-            template.instantiate(runtime, initializeNode, initializeNode, arguments);
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.snippets;
+
+import static com.oracle.graal.hotspot.nodes.CastFromHub.*;
+import static com.oracle.graal.hotspot.nodes.RegisterNode.*;
+import static com.oracle.graal.hotspot.snippets.DirectObjectStoreNode.*;
+import static com.oracle.graal.nodes.extended.UnsafeLoadNode.*;
+import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*;
+import static com.oracle.graal.snippets.nodes.ExplodeLoopNode.*;
+import static com.oracle.max.asm.target.amd64.AMD64.*;
+import static com.oracle.max.criutils.UnsignedMath.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.snippets.*;
+import com.oracle.graal.snippets.Snippet.ConstantParameter;
+import com.oracle.graal.snippets.Snippet.Fold;
+import com.oracle.graal.snippets.Snippet.Parameter;
+import com.oracle.graal.snippets.SnippetTemplate.Arguments;
+import com.oracle.graal.snippets.SnippetTemplate.Cache;
+import com.oracle.graal.snippets.SnippetTemplate.Key;
+
+/**
+ * Snippets used for implementing NEW, ANEWARRAY and NEWARRAY.
+ */
+public class NewObjectSnippets implements SnippetsInterface {
+
+    @Snippet
+    public static Word allocate(@Parameter("size") int size) {
+        Word thread = asWord(register(r15, wordKind()));
+        Word top = loadWord(thread, threadTlabTopOffset());
+        Word end = loadWord(thread, threadTlabEndOffset());
+        Word newTop = top.plus(size);
+        if (newTop.belowOrEqual(end)) {
+            storeObject(thread, 0, threadTlabTopOffset(), newTop);
+            return top;
+        }
+        return Word.zero();
+    }
+
+    @Snippet
+    public static Object initializeObject(
+                    @Parameter("memory") Word memory,
+                    @Parameter("hub") Object hub,
+                    @Parameter("initialMarkWord") Word initialMarkWord,
+                    @ConstantParameter("size") int size) {
+
+        if (memory == Word.zero()) {
+            return NewInstanceStubCall.call(hub);
+        }
+        formatObject(hub, size, memory, initialMarkWord);
+        Object instance = memory.toObject();
+        return castFromHub(verifyOop(instance), hub);
+    }
+
+    @Snippet
+    public static Object initializeObjectArray(
+                    @Parameter("memory") Word memory,
+                    @Parameter("hub") Object hub,
+                    @Parameter("length") int length,
+                    @Parameter("size") int size,
+                    @Parameter("initialMarkWord") Word initialMarkWord,
+                    @ConstantParameter("headerSize") int headerSize) {
+        return initializeArray(memory, hub, length, size, initialMarkWord, headerSize, true);
+    }
+
+    @Snippet
+    public static Object initializePrimitiveArray(
+                    @Parameter("memory") Word memory,
+                    @Parameter("hub") Object hub,
+                    @Parameter("length") int length,
+                    @Parameter("size") int size,
+                    @Parameter("initialMarkWord") Word initialMarkWord,
+                    @ConstantParameter("headerSize") int headerSize) {
+        return initializeArray(memory, hub, length, size, initialMarkWord, headerSize, false);
+    }
+
+    private static Object initializeArray(Word memory, Object hub, int length, int size, Word initialMarkWord, int headerSize, boolean isObjectArray) {
+        if (memory == Word.zero()) {
+            return NewArrayStubCall.call(isObjectArray, hub, length);
+        }
+        formatArray(hub, size, length, headerSize, memory, initialMarkWord);
+        Object instance = memory.toObject();
+        return castFromHub(verifyOop(instance), hub);
+    }
+
+    /**
+     * Maximum array length for which fast path allocation is used.
+     */
+    private static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF;
+
+    @Snippet
+    public static Object allocateArrayAndInitialize(
+                    @Parameter("length") int length,
+                    @ConstantParameter("alignment") int alignment,
+                    @ConstantParameter("headerSize") int headerSize,
+                    @ConstantParameter("log2ElementSize") int log2ElementSize,
+                    @ConstantParameter("type") ResolvedJavaType type,
+                    @ConstantParameter("wordKind") Kind wordKind) {
+        if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) {
+            // This handles both negative array sizes and very large array sizes
+            DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.RuntimeConstraint);
+        }
+        int size = getArraySize(length, alignment, headerSize, log2ElementSize);
+        Word memory = TLABAllocateNode.allocateVariableSize(wordKind, size);
+        return InitializeArrayNode.initialize(memory, length, size, type);
+    }
+
+    public static int getArraySize(int length, int alignment, int headerSize, int log2ElementSize) {
+        int size = (length << log2ElementSize) + headerSize + (alignment - 1);
+        int mask = ~(alignment - 1);
+        return size & mask;
+    }
+
+    private static Object verifyOop(Object object) {
+        if (verifyOops()) {
+            VerifyOopStubCall.call(object);
+        }
+        return object;
+    }
+
+    private static Word asWord(Object object) {
+        return Word.fromObject(object);
+    }
+
+    private static Word loadWord(Word address, int offset) {
+        Object value = loadObject(address, 0, offset, true);
+        return asWord(value);
+    }
+
+    /**
+     * Maximum size of an object whose body is initialized by a sequence of
+     * zero-stores to its fields. Larger objects have their bodies initialized
+     * in a loop.
+     */
+    private static final int MAX_UNROLLED_OBJECT_ZEROING_SIZE = 10 * wordSize();
+
+    /**
+     * Formats some allocated memory with an object header zeroes out the rest.
+     */
+    private static void formatObject(Object hub, int size, Word memory, Word headerPrototype) {
+        storeObject(memory, 0, markOffset(), headerPrototype);
+        storeObject(memory, 0, hubOffset(), hub);
+        if (size <= MAX_UNROLLED_OBJECT_ZEROING_SIZE) {
+            explodeLoop();
+            for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) {
+                storeWord(memory, 0, offset, Word.zero());
+            }
+        } else {
+            for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) {
+                storeWord(memory, 0, offset, Word.zero());
+            }
+        }
+    }
+
+    /**
+     * Formats some allocated memory with an object header zeroes out the rest.
+     */
+    private static void formatArray(Object hub, int size, int length, int headerSize, Word memory, Word headerPrototype) {
+        storeObject(memory, 0, markOffset(), headerPrototype);
+        storeObject(memory, 0, hubOffset(), hub);
+        storeInt(memory, 0, arrayLengthOffset(), length);
+        for (int offset = headerSize; offset < size; offset += wordSize()) {
+            storeWord(memory, 0, offset, Word.zero());
+        }
+    }
+
+    public static class Templates {
+
+        private final Cache cache;
+        private final ResolvedJavaMethod allocate;
+        private final ResolvedJavaMethod initializeObject;
+        private final ResolvedJavaMethod initializeObjectArray;
+        private final ResolvedJavaMethod initializePrimitiveArray;
+        private final ResolvedJavaMethod allocateArrayAndInitialize;
+        private final TargetDescription target;
+        private final CodeCacheProvider runtime;
+        private final boolean useTLAB;
+
+        public Templates(CodeCacheProvider runtime, TargetDescription target, boolean useTLAB) {
+            this.runtime = runtime;
+            this.target = target;
+            this.cache = new Cache(runtime);
+            this.useTLAB = useTLAB;
+            try {
+                allocate = runtime.getResolvedJavaMethod(NewObjectSnippets.class.getDeclaredMethod("allocate", int.class));
+                initializeObject = runtime.getResolvedJavaMethod(NewObjectSnippets.class.getDeclaredMethod("initializeObject", Word.class, Object.class, Word.class, int.class));
+                initializeObjectArray = runtime.getResolvedJavaMethod(NewObjectSnippets.class.getDeclaredMethod("initializeObjectArray", Word.class, Object.class, int.class, int.class, Word.class, int.class));
+                initializePrimitiveArray = runtime.getResolvedJavaMethod(NewObjectSnippets.class.getDeclaredMethod("initializePrimitiveArray", Word.class, Object.class, int.class, int.class, Word.class, int.class));
+                allocateArrayAndInitialize = runtime.getResolvedJavaMethod(NewObjectSnippets.class.getDeclaredMethod("allocateArrayAndInitialize", int.class, int.class, int.class, int.class, ResolvedJavaType.class, Kind.class));
+            } catch (NoSuchMethodException e) {
+                throw new GraalInternalError(e);
+            }
+        }
+
+        /**
+         * Lowers a {@link NewInstanceNode}.
+         */
+        @SuppressWarnings("unused")
+        public void lower(NewInstanceNode newInstanceNode, LoweringTool tool) {
+            StructuredGraph graph = (StructuredGraph) newInstanceNode.graph();
+            HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) newInstanceNode.instanceClass();
+            HotSpotKlassOop hub = type.klassOop();
+            int size = type.instanceSize();
+            assert (size % wordSize()) == 0;
+            assert size >= 0;
+
+            ValueNode memory;
+            if (!useTLAB) {
+                memory = ConstantNode.forConstant(new Constant(target.wordKind, 0L), runtime, graph);
+            } else {
+                TLABAllocateNode tlabAllocateNode = graph.add(new TLABAllocateNode(size, wordKind()));
+                graph.addBeforeFixed(newInstanceNode, tlabAllocateNode);
+                memory = tlabAllocateNode;
+            }
+            InitializeObjectNode initializeNode = graph.add(new InitializeObjectNode(memory, type));
+            graph.replaceFixedWithFixed(newInstanceNode, initializeNode);
+        }
+
+        /**
+         * Lowers a {@link NewArrayNode}.
+         */
+        @SuppressWarnings("unused")
+        public void lower(NewArrayNode newArrayNode, LoweringTool tool) {
+            StructuredGraph graph = (StructuredGraph) newArrayNode.graph();
+            ValueNode lengthNode = newArrayNode.length();
+            TLABAllocateNode tlabAllocateNode;
+            ResolvedJavaType elementType = newArrayNode.elementType();
+            ResolvedJavaType arrayType = elementType.arrayOf();
+            Kind elementKind = elementType.kind();
+            final int alignment = target.wordSize;
+            final int headerSize = elementKind.arrayBaseOffset();
+            final Integer length = lengthNode.isConstant() ? Integer.valueOf(lengthNode.asConstant().asInt()) : null;
+            int log2ElementSize = CodeUtil.log2(target.sizeInBytes(elementKind));
+            if (!useTLAB) {
+                ConstantNode zero = ConstantNode.forConstant(new Constant(target.wordKind, 0L), runtime, graph);
+                // value for 'size' doesn't matter as it isn't used since a stub call will be made anyway
+                // for both allocation and initialization - it just needs to be non-null
+                ConstantNode size = ConstantNode.forInt(-1, graph);
+                InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(zero, lengthNode, size, arrayType));
+                graph.replaceFixedWithFixed(newArrayNode, initializeNode);
+            } else if (length != null && belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) {
+                // Calculate aligned size
+                int size = getArraySize(length, alignment, headerSize, log2ElementSize);
+                ConstantNode sizeNode = ConstantNode.forInt(size, graph);
+                tlabAllocateNode = graph.add(new TLABAllocateNode(size, target.wordKind));
+                graph.addBeforeFixed(newArrayNode, tlabAllocateNode);
+                InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(tlabAllocateNode, lengthNode, sizeNode, arrayType));
+                graph.replaceFixedWithFixed(newArrayNode, initializeNode);
+            } else {
+                Key key = new Key(allocateArrayAndInitialize).
+                                add("alignment", alignment).
+                                add("headerSize", headerSize).
+                                add("log2ElementSize", log2ElementSize).
+                                add("wordKind", target.wordKind).
+                                add("type", arrayType);
+                Arguments arguments = new Arguments().add("length", lengthNode);
+                SnippetTemplate template = cache.get(key);
+                Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, arguments);
+                template.instantiate(runtime, newArrayNode, newArrayNode, arguments);
+            }
+        }
+
+        @SuppressWarnings("unused")
+        public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) {
+            StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph();
+            ValueNode size;
+            if (tlabAllocateNode.isSizeConstant()) {
+                size = ConstantNode.forInt(tlabAllocateNode.constantSize(), graph);
+            } else {
+                size = tlabAllocateNode.variableSize();
+            }
+            Key key = new Key(allocate);
+            Arguments arguments = arguments("size", size);
+            SnippetTemplate template = cache.get(key);
+            Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments);
+            template.instantiate(runtime, tlabAllocateNode, tlabAllocateNode, arguments);
+        }
+
+        @SuppressWarnings("unused")
+        public void lower(InitializeObjectNode initializeNode, LoweringTool tool) {
+            StructuredGraph graph = (StructuredGraph) initializeNode.graph();
+            HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) initializeNode.type();
+            assert !type.isArrayClass();
+            HotSpotKlassOop hub = type.klassOop();
+            int size = type.instanceSize();
+            assert (size % wordSize()) == 0;
+            assert size >= 0;
+            Key key = new Key(initializeObject).add("size", size);
+            ValueNode memory = initializeNode.memory();
+            Arguments arguments = arguments("memory", memory).add("hub", hub).add("initialMarkWord", type.initialMarkWord());
+            SnippetTemplate template = cache.get(key);
+            Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments);
+            template.instantiate(runtime, initializeNode, initializeNode, arguments);
+        }
+
+        @SuppressWarnings("unused")
+        public void lower(InitializeArrayNode initializeNode, LoweringTool tool) {
+            StructuredGraph graph = (StructuredGraph) initializeNode.graph();
+            HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) initializeNode.type();
+            ResolvedJavaType elementType = type.componentType();
+            assert elementType != null;
+            HotSpotKlassOop hub = type.klassOop();
+            Kind elementKind = elementType.kind();
+            final int headerSize = elementKind.arrayBaseOffset();
+            Key key = new Key(elementKind.isObject() ? initializeObjectArray : initializePrimitiveArray).add("headerSize", headerSize);
+            ValueNode memory = initializeNode.memory();
+            Arguments arguments = arguments("memory", memory).add("hub", hub).add("initialMarkWord", type.initialMarkWord()).add("size", initializeNode.size()).add("length", initializeNode.length());
+            SnippetTemplate template = cache.get(key);
+            Debug.log("Lowering initializeObjectArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments);
+            template.instantiate(runtime, initializeNode, initializeNode, arguments);
+        }
+    }
+
+    @Fold
+    private static boolean verifyOops() {
+        return HotSpotGraalRuntime.getInstance().getConfig().verifyOops;
+    }
+
+    @Fold
+    private static int threadTlabTopOffset() {
+        return HotSpotGraalRuntime.getInstance().getConfig().threadTlabTopOffset;
+    }
+
+    @Fold
+    private static int threadTlabEndOffset() {
+        return HotSpotGraalRuntime.getInstance().getConfig().threadTlabEndOffset;
+    }
+
+    @Fold
+    private static Kind wordKind() {
+        return HotSpotGraalRuntime.getInstance().getTarget().wordKind;
+    }
+
+    @Fold
+    private static int wordSize() {
+        return HotSpotGraalRuntime.getInstance().getTarget().wordSize;
+    }
+
+    @Fold
+    private static int markOffset() {
+        return HotSpotGraalRuntime.getInstance().getConfig().markOffset;
+    }
+
+    @Fold
+    private static int hubOffset() {
+        return HotSpotGraalRuntime.getInstance().getConfig().hubOffset;
+    }
+
+    @Fold
+    private static int arrayLengthOffset() {
+        return HotSpotGraalRuntime.getInstance().getConfig().arrayLengthOffset;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/UnsignedMathSnippets.java	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,86 @@
+/*
+ * 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.graal.hotspot.snippets;
+
+import static com.oracle.graal.nodes.MaterializeNode.*;
+import static com.oracle.graal.nodes.calc.Condition.*;
+
+import com.oracle.graal.snippets.*;
+import com.oracle.max.criutils.*;
+
+/**
+ * Snippets for {@link UnsignedMath}.
+ */
+@ClassSubstitution(UnsignedMath.class)
+public class UnsignedMathSnippets implements SnippetsInterface {
+
+    public static boolean aboveThan(int a, int b) {
+        return materialize(BT, b, a);
+    }
+
+    public static boolean aboveOrEqual(int a, int b) {
+        return !materialize(BT, a, b);
+    }
+
+    /**
+     * Unsigned comparison belowThan for two numbers.
+     */
+    public static boolean belowThan(int a, int b) {
+        return materialize(BT, a, b);
+    }
+
+    /**
+     * Unsigned comparison belowOrEqual for two numbers.
+     */
+    public static boolean belowOrEqual(int a, int b) {
+        return !materialize(BT, b, a);
+    }
+
+    /**
+     * Unsigned comparison aboveThan for two numbers.
+     */
+    public static boolean aboveThan(long a, long b) {
+        return materialize(BT, b, a);
+    }
+
+    /**
+     * Unsigned comparison aboveOrEqual for two numbers.
+     */
+    public static boolean aboveOrEqual(long a, long b) {
+        return !materialize(BT, a, b);
+    }
+
+    /**
+     * Unsigned comparison belowThan for two numbers.
+     */
+    public static boolean belowThan(long a, long b) {
+        return materialize(BT, a, b);
+    }
+
+    /**
+     * Unsigned comparison belowOrEqual for two numbers.
+     */
+    public static boolean belowOrEqual(long a, long b) {
+        return !materialize(BT, b, a);
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java	Thu Jul 05 16:54:00 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.target;
-
-import static com.oracle.graal.api.code.ValueUtil.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.amd64.*;
-import com.oracle.graal.lir.asm.*;
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
-
-/**
- * LIR instruction for calling HotSpot's {@code new_instance} stub. This stub is declared in c1_Runtime1.hpp
- * and implemented in Runtime1::generate_code_for() which is located in c1_Runtime1_x86.cpp.
- */
-@Opcode("NEW_INSTANCE")
-public class AMD64NewInstanceStubCallOp extends AMD64LIRInstruction {
-    @Def protected Value result;
-    @Use protected Value hub;
-    @Temp protected Value temp;
-    @State protected LIRFrameState state;
-
-    public AMD64NewInstanceStubCallOp(Value result, Value hub, LIRFrameState state) {
-        this.result = result;
-        this.hub = hub;
-        this.temp = AMD64.rax.asValue(Kind.Object);
-        this.state = state;
-    }
-
-    @Override
-    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        // rdx: (in) hub
-        // rax: (out) result
-        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().newInstanceStub, state);
-        if (asRegister(result) != AMD64.rax) {
-            masm.movq(asRegister(result), AMD64.rax);
-        }
-    }
-
-    @Override
-    protected void verify() {
-        super.verify();
-        assert asRegister(hub) == AMD64.rdx;
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java	Thu Jul 05 16:54:00 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.target;
-
-import static com.oracle.graal.api.code.ValueUtil.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
-import com.oracle.graal.lir.amd64.*;
-import com.oracle.graal.lir.asm.*;
-import com.oracle.max.asm.target.amd64.*;
-
-/**
- * A call to HotSpot's object pointer verification stub.
- */
-@Opcode("VERIFY_OOP")
-public class AMD64VerifyOopStubCallOp extends AMD64LIRInstruction {
-    @Use protected Value object;
-    @State protected LIRFrameState state;
-
-    public AMD64VerifyOopStubCallOp(Value object, LIRFrameState state) {
-        this.object = object;
-        this.state = state;
-    }
-
-    @Override
-    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        // r13: (in) object
-        if (asRegister(object) != AMD64.r13) {
-            masm.push(AMD64.r13);
-            masm.movq(AMD64.r13, asRegister(object));
-        }
-        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, state);
-        if (asRegister(object) != AMD64.r13) {
-            masm.pop(AMD64.r13);
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64NewArrayStubCallOp.java	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.target.amd64;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+
+/**
+ * LIR instruction for calling HotSpot's {@code new_[object|type]_array} stub. This stub is declared in c1_Runtime1.hpp
+ * and implemented in Runtime1::generate_code_for() which is located in c1_Runtime1_x86.cpp.
+ */
+@Opcode("NEW_ARRAY")
+public class AMD64NewArrayStubCallOp extends AMD64LIRInstruction {
+
+    /**
+     * The stub places the result in RAX.
+     */
+    public static final Register RESULT = AMD64.rax;
+
+    /**
+     * The stub expects the hub in RDX.
+     */
+    public static final Register HUB = AMD64.rdx;
+
+    /**
+     * The stub expects the length in RBX.
+     */
+    public static final Register LENGTH = AMD64.rbx;
+
+    /**
+     * The stub uses RCX, RSI, and RDI as temps.
+     */
+    public static final Register[] TEMPS = {AMD64.rcx, AMD64.rdi, AMD64.rsi};
+
+    private final boolean isObjectArray;
+
+    @Def protected Value result;
+    @Use protected Value hub;
+    @Use protected Value length;
+    @Temp protected Value[] temps;
+
+    @State protected LIRFrameState state;
+
+    public AMD64NewArrayStubCallOp(boolean isObjectArray, Value result, Value hub, Value length, LIRFrameState state) {
+        this.isObjectArray = isObjectArray;
+        this.result = result;
+        this.hub = hub;
+        this.length = length;
+        this.temps = new Value[TEMPS.length];
+        for (int i = 0; i < temps.length; i++) {
+            temps[i] = TEMPS[i].asValue(Kind.Long);
+        }
+        this.state = state;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig();
+        long stub = isObjectArray ? config.newObjectArrayStub : config.newTypeArrayStub;
+        AMD64Call.directCall(tasm, masm, stub, state);
+    }
+
+    @Override
+    protected void verify() {
+        super.verify();
+        assert asRegister(hub) == HUB : "stub expects hub in " + HUB;
+        assert asRegister(length) == LENGTH : "stub expect length in " + LENGTH;
+        assert asRegister(result) == RESULT : "stub places result in " + RESULT;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64NewInstanceStubCallOp.java	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.target.amd64;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+
+/**
+ * LIR instruction for calling HotSpot's {@code new_instance} stub. This stub is declared in c1_Runtime1.hpp
+ * and implemented in Runtime1::generate_code_for() which is located in c1_Runtime1_x86.cpp.
+ */
+@Opcode("NEW_INSTANCE")
+public class AMD64NewInstanceStubCallOp extends AMD64LIRInstruction {
+
+    /**
+     * The stub expects the hub in RDX.
+     */
+    public static final Register HUB = AMD64.rdx;
+
+    /**
+     * The stub places the result in RAX.
+     */
+    public static final Register RESULT = AMD64.rax;
+
+    @Def protected Value result;
+    @Use protected Value hub;
+    @State protected LIRFrameState state;
+
+    public AMD64NewInstanceStubCallOp(Value result, Value hub, LIRFrameState state) {
+        this.hub = hub;
+        this.result = result;
+        this.state = state;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().newInstanceStub, state);
+    }
+
+    @Override
+    protected void verify() {
+        super.verify();
+        assert asRegister(hub) == HUB : "expects hub in " + HUB;
+        assert asRegister(result) == RESULT : "expects result in " + RESULT;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64VerifyOopStubCallOp.java	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.target.amd64;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+
+/**
+ * A call to HotSpot's object pointer verification stub.
+ */
+@Opcode("VERIFY_OOP")
+public class AMD64VerifyOopStubCallOp extends AMD64LIRInstruction {
+
+    /**
+     * The stub expects the object pointer in R13.
+     */
+    public static final Register OBJECT = AMD64.r13;
+
+    @Use protected Value object;
+    @State protected LIRFrameState state;
+
+    public AMD64VerifyOopStubCallOp(Value object, LIRFrameState state) {
+        this.object = object;
+        this.state = state;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, state);
+    }
+
+    @Override
+    protected void verify() {
+        super.verify();
+        assert asRegister(object) == OBJECT : "expects object in " + OBJECT;
+    }
+}
--- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java	Thu Jul 05 16:54:45 2012 +0200
@@ -25,22 +25,14 @@
 import java.lang.reflect.*;
 import java.util.*;
 
+import com.oracle.graal.api.*;
 import com.oracle.graal.api.interpreter.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.bytecode.*;
 
 /**
- *
- * <h1>Implementation notes</h1>
- * <li>Native methods are invoked using standard java reflection.</li>
- *
- * <h1>Features:</h1>
- *
- *
- * <h1>Limitations:</h1>
- *
- * <li>The interpreter is not able to recognize a native method that calls a java method.
- *  In that case the java method will be interpreted directly on the vm interpreter.</li>
+ * High-level bytecode interpreter that executes on top of Java. Java native methods
+ * are executed using the {@link com.oracle.graal.api.interpreter.RuntimeInterpreterInterface}.
  */
 @SuppressWarnings("static-method")
 public final class BytecodeInterpreter implements Interpreter {
@@ -49,7 +41,7 @@
     private static final boolean TRACE = false;
     private static final boolean TRACE_BYTE_CODE = false;
 
-    private static final int DEFAULT_MAX_STACK_SIZE = 200;
+    private static final int DEFAULT_MAX_STACK_SIZE = 1500;
 
     private static final int NEXT = -1;
     private static final int BRANCH = -2;
@@ -58,28 +50,31 @@
 
     private InterpreterFrame callFrame;
 
-    //TODO try to remove this reference
-    private ExceptionHandler catchAllExceptionHandler;
+    private Map<ResolvedJavaMethod, MethodRedirectionInfo> methodDelegates;
+
+    private int maxStackFrames;
 
-    private final Map<ResolvedJavaMethod, InterpreterCallable> methodDelegates = new HashMap<>();
-
-    private int maxStackFrames = DEFAULT_MAX_STACK_SIZE;
-    private int stackFrameDepth;
+    private ResolvedJavaMethod rootMethod;
+    private RuntimeInterpreterInterface runtimeInterface;
+    private MetaAccessProvider metaAccessProvider;
 
-    private final ResolvedJavaMethod rootMethod;
-    private final VMAdapter vm;
+    public boolean initialize(String args) {
+        methodDelegates = new HashMap<>();
+        maxStackFrames = DEFAULT_MAX_STACK_SIZE;
 
-    public BytecodeInterpreter() {
-        this(VMAdapter.getInstance());
-    }
+        GraalRuntime runtime = Graal.getRuntime();
+        this.runtimeInterface = runtime.getCapability(RuntimeInterpreterInterface.class);
+        if (this.runtimeInterface == null) {
+            throw new UnsupportedOperationException("The provided graal runtime does not support the required capability " + RuntimeInterpreterInterface.class.getName() + ".");
+        }
+        this.metaAccessProvider = runtime.getCapability(MetaAccessProvider.class);
+        if (this.metaAccessProvider == null) {
+            throw new UnsupportedOperationException("The provided graal runtime does not support the required capability " + MetaAccessProvider.class.getName() + ".");
+        }
 
-    public BytecodeInterpreter(VMAdapter accessor) {
-        if (accessor == null) {
-            throw new NullPointerException();
-        }
-        this.vm = accessor;
         this.rootMethod = resolveRootMethod();
         registerDelegates();
+        return parseArguments(args);
     }
 
     @Override
@@ -89,38 +84,46 @@
         }
     }
 
+    private void registerDelegates() {
+        addDelegate(findMethod(Throwable.class, "fillInStackTrace"), new InterpreterCallable() {
 
-    private void registerDelegates() {
-       addDelegate(findMethod(Throwable.class, "fillInStackTrace"), new InterpreterCallable() {
-        @Override
-        public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object base, Object[] arguments) throws Throwable {
-            setBackTrace(caller, (Throwable) base, createStackTraceElements(caller));
-            return null;
-        }
-       });
-       addDelegate(findMethod(Throwable.class, "getStackTraceDepth"), new InterpreterCallable() {
-           @Override
-           public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object base, Object[] arguments) throws Throwable {
-               StackTraceElement[] elements = getBackTrace(caller, (Throwable) base);
-               if (elements != null) {
-                   return elements.length;
-               }
-               return 0;
-           }
-       });
-       addDelegate(findMethod(Throwable.class, "getStackTraceElement", int.class), new InterpreterCallable() {
-           @Override
-           public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object base, Object[] arguments) throws Throwable {
-               StackTraceElement[] elements = getBackTrace(caller, (Throwable) base);
-               if (elements != null) {
-                   Integer index = (Integer) arguments[0];
-                   if (index != null) {
-                       return elements[index];
-                   }
-               }
-               return null;
-           }
-       });
+            @Override
+            public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable {
+                setBackTrace(caller, (Throwable) arguments[0], createStackTraceElements(caller));
+                return null;
+            }
+        });
+        addDelegate(findMethod(Throwable.class, "getStackTraceDepth"), new InterpreterCallable() {
+
+            @Override
+            public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable {
+                StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]);
+                if (elements != null) {
+                    return elements.length;
+                }
+                return 0;
+            }
+        });
+        addDelegate(findMethod(Throwable.class, "getStackTraceElement", int.class), new InterpreterCallable() {
+
+            @Override
+            public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable {
+                StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]);
+                if (elements != null) {
+                    Integer index = (Integer) arguments[0];
+                    if (index != null) {
+                        return elements[index];
+                    }
+                }
+                return null;
+            }
+        });
+    }
+
+    @SuppressWarnings("unused")
+    private boolean parseArguments(String stringArgs) {
+        // TODO: parse the arguments
+        return true;
     }
 
     public void setMaxStackFrames(int maxStackSize) {
@@ -132,59 +135,64 @@
     }
 
     public void addDelegate(Method method, InterpreterCallable callable) {
-        ResolvedJavaMethod resolvedMethod = vm.getRuntime().getResolvedJavaMethod(method);
+        ResolvedJavaMethod resolvedMethod = metaAccessProvider.getResolvedJavaMethod(method);
         if (methodDelegates.containsKey(resolvedMethod)) {
             throw new IllegalArgumentException("Delegate for method " + method + " already added.");
         }
-        methodDelegates.put(resolvedMethod, callable);
+
+        methodDelegates.put(resolvedMethod, new MethodRedirectionInfo(callable));
     }
 
     public void removeDelegate(Method method) {
-        methodDelegates.remove(vm.getRuntime().getResolvedJavaMethod(method));
+        methodDelegates.remove(metaAccessProvider.getResolvedJavaMethod(method));
     }
 
     @Override
-    public Object execute(ResolvedJavaMethod method, Object... boxedArguments) {
-        Signature signature = method.signature();
-        assert boxedArguments != null;
-        assert signature.argumentCount(false) == boxedArguments.length;
+    public Object execute(ResolvedJavaMethod method, Object... boxedArguments) throws Throwable {
+        try {
+            boolean receiver = hasReceiver(method);
+            Signature signature = method.signature();
+            assert boxedArguments != null;
+            assert signature.argumentCount(receiver) == boxedArguments.length;
 
-        if (!Modifier.isStatic(method.accessFlags())) {
-            throw new UnsupportedOperationException("The interpreter can currently only be started with static methods.");
-        }
+            if (TRACE) {
+                trace(0, "Executing root method " + method);
+            }
 
-        InterpreterFrame rootFrame = new InterpreterFrame(rootMethod, signature.argumentSlots(true));
-        rootFrame.pushObject(this);
-        rootFrame.pushObject(method);
-        rootFrame.pushObject(boxedArguments);
+            InterpreterFrame rootFrame = new InterpreterFrame(rootMethod, signature.argumentSlots(true));
+            rootFrame.pushObject(this);
+            rootFrame.pushObject(method);
+            rootFrame.pushObject(boxedArguments);
 
-        for (int i = 0; i < boxedArguments.length; i++) {
-            pushAsObject(rootFrame, signature.argumentKindAt(i), boxedArguments[i]);
-        }
+            int index = 0;
+            if (receiver) {
+                pushAsObject(rootFrame, Kind.Object, boxedArguments[index]);
+                index++;
+            }
 
-        InterpreterFrame frame = rootFrame.create(method, false);
+            for (int i = 0; index < boxedArguments.length; i++, index++) {
+                pushAsObject(rootFrame, signature.argumentKindAt(i), boxedArguments[index]);
+            }
 
-        try {
+            InterpreterFrame frame = rootFrame.create(method, receiver);
             executeRoot(rootFrame, frame);
-        } catch (Throwable e) {
-            // clear backtrace for compatibilty and store it in stacktrace
-            StackTraceElement[] backtrace = getBackTrace(rootFrame, e);
-            setBackTrace(rootFrame, e, null);
-            setStackTrace(rootFrame, e, backtrace);
-            throw new InterpreterException(e);
+            return popAsObject(rootFrame, signature.returnKind());
+        } catch (Exception e) {
+            // TODO (chaeubl): remove this exception handler (only used for debugging)
+            throw e;
         }
-
-        return popAsObject(rootFrame, signature.returnKind());
     }
 
-    public Object execute(Method javaMethod, Object... boxedArguments) throws InterpreterException {
-        return execute(vm.getRuntime().getResolvedJavaMethod(javaMethod), boxedArguments);
+    public Object execute(Method javaMethod, Object... boxedArguments) throws Throwable {
+        return execute(metaAccessProvider.getResolvedJavaMethod(javaMethod), boxedArguments);
+    }
+
+    private boolean hasReceiver(ResolvedJavaMethod method) {
+        return !Modifier.isStatic(method.accessFlags());
     }
 
     private void executeRoot(InterpreterFrame root, InterpreterFrame frame) throws Throwable {
-        //TODO reflection redirection
-        stackFrameDepth = 0;
-
+        // TODO reflection redirection
         InterpreterFrame prevFrame = frame;
         InterpreterFrame currentFrame = frame;
         BytecodeStream bs = new BytecodeStream(currentFrame.getMethod().code());
@@ -208,17 +216,17 @@
             while (true) {
                 int result = executeInstruction(frame, bs);
                 switch (result) {
-                    case NEXT :
+                    case NEXT:
                         bs.next();
                         break;
-                    case RETURN :
+                    case RETURN:
                         return popFrame(frame);
                     case CALL:
                         return allocateFrame(frame, bs);
-                    case BRANCH :
+                    case BRANCH:
                         bs.setBCI(bs.readBranchDest());
                         break;
-                    default :
+                    default:
                         // the outcome depends on stack values
                         assert result >= 0 : "negative branch target";
                         bs.setBCI(result);
@@ -227,7 +235,7 @@
             }
         } catch (Throwable t) {
             if (TRACE) {
-                traceOp("Exception " + t.toString());
+                traceOp(frame, "Exception " + t.toString());
             }
             updateStackTrace(frame, t);
 
@@ -240,7 +248,7 @@
                 throw t;
             } else {
                 if (TRACE) {
-                    traceOp("Handler found " + handlerFrame.getMethod() + ":" + handlerFrame.getBCI());
+                    traceOp(frame, "Handler found " + handlerFrame.getMethod() + ":" + handlerFrame.getBCI());
                 }
                 // update bci from frame
                 bs.setBCI(handlerFrame.getBCI());
@@ -256,79 +264,80 @@
 
     private int executeInstruction(InterpreterFrame frame, BytecodeStream bs) throws Throwable {
         if (TRACE_BYTE_CODE) {
-            traceOp(bs.currentBCI() + ": " + Bytecodes.baseNameOf(bs.currentBC()));
+            traceOp(frame, bs.currentBCI() + ": " + Bytecodes.baseNameOf(bs.currentBC()));
         }
-        switch(bs.currentBC()) {
-            case Bytecodes.NOP            : break;
-            case Bytecodes.ACONST_NULL    :
+        switch (bs.currentBC()) {
+            case Bytecodes.NOP:
+                break;
+            case Bytecodes.ACONST_NULL:
                 frame.pushObject(null);
                 break;
-            case Bytecodes.ICONST_M1      :
+            case Bytecodes.ICONST_M1:
                 frame.pushInt(-1);
                 break;
-            case Bytecodes.ICONST_0       :
+            case Bytecodes.ICONST_0:
                 frame.pushInt(0);
                 break;
-            case Bytecodes.ICONST_1       :
+            case Bytecodes.ICONST_1:
                 frame.pushInt(1);
                 break;
-            case Bytecodes.ICONST_2       :
+            case Bytecodes.ICONST_2:
                 frame.pushInt(2);
                 break;
-            case Bytecodes.ICONST_3       :
+            case Bytecodes.ICONST_3:
                 frame.pushInt(3);
                 break;
-            case Bytecodes.ICONST_4       :
+            case Bytecodes.ICONST_4:
                 frame.pushInt(4);
                 break;
-            case Bytecodes.ICONST_5       :
+            case Bytecodes.ICONST_5:
                 frame.pushInt(5);
                 break;
-            case Bytecodes.LCONST_0       :
+            case Bytecodes.LCONST_0:
                 frame.pushLong(0L);
                 break;
-            case Bytecodes.LCONST_1       :
+            case Bytecodes.LCONST_1:
                 frame.pushLong(1L);
                 break;
-            case Bytecodes.FCONST_0       :
+            case Bytecodes.FCONST_0:
                 frame.pushFloat(0.0F);
                 break;
-            case Bytecodes.FCONST_1       :
+            case Bytecodes.FCONST_1:
                 frame.pushFloat(1.0F);
                 break;
-            case Bytecodes.FCONST_2       :
+            case Bytecodes.FCONST_2:
                 frame.pushFloat(2.0F);
                 break;
-            case Bytecodes.DCONST_0       :
+            case Bytecodes.DCONST_0:
                 frame.pushDouble(0.0D);
                 break;
-            case Bytecodes.DCONST_1       :
+            case Bytecodes.DCONST_1:
                 frame.pushDouble(1.0D);
                 break;
-            case Bytecodes.BIPUSH         :
+            case Bytecodes.BIPUSH:
                 frame.pushInt(bs.readByte());
                 break;
-            case Bytecodes.SIPUSH         :
+            case Bytecodes.SIPUSH:
                 frame.pushInt(bs.readShort());
                 break;
-            case Bytecodes.LDC            :
-            case Bytecodes.LDC_W          :
-            case Bytecodes.LDC2_W         :
+            case Bytecodes.LDC:
+            case Bytecodes.LDC_W:
+            case Bytecodes.LDC2_W:
                 pushCPConstant(frame, bs.readCPI());
                 break;
-            case Bytecodes.ILOAD          :
+            case Bytecodes.ILOAD:
                 frame.pushInt(frame.getInt(frame.resolveLocalIndex(bs.readLocalIndex())));
                 break;
-            case Bytecodes.LLOAD          :
+            case Bytecodes.LLOAD:
                 frame.pushLong(frame.getLong(frame.resolveLocalIndex(bs.readLocalIndex())));
                 break;
-            case Bytecodes.FLOAD          :
+            case Bytecodes.FLOAD:
                 frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(bs.readLocalIndex())));
                 break;
-            case Bytecodes.DLOAD          :
+            case Bytecodes.DLOAD:
                 frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(bs.readLocalIndex())));
                 break;
-            case Bytecodes.ALOAD          :
+            case Bytecodes.ALOAD:
                 frame.pushObject(frame.getObject(frame.resolveLocalIndex(bs.readLocalIndex())));
                 break;
             case Bytecodes.ILOAD_0:
@@ -343,441 +352,441 @@
             case Bytecodes.ILOAD_3:
                 frame.pushInt(frame.getInt(frame.resolveLocalIndex(3)));
                 break;
-            case Bytecodes.LLOAD_0        :
+            case Bytecodes.LLOAD_0:
                 frame.pushLong(frame.getLong(frame.resolveLocalIndex(0)));
                 break;
-            case Bytecodes.LLOAD_1        :
+            case Bytecodes.LLOAD_1:
                 frame.pushLong(frame.getLong(frame.resolveLocalIndex(1)));
                 break;
-            case Bytecodes.LLOAD_2        :
+            case Bytecodes.LLOAD_2:
                 frame.pushLong(frame.getLong(frame.resolveLocalIndex(2)));
                 break;
-            case Bytecodes.LLOAD_3        :
+            case Bytecodes.LLOAD_3:
                 frame.pushLong(frame.getLong(frame.resolveLocalIndex(3)));
                 break;
-            case Bytecodes.FLOAD_0        :
+            case Bytecodes.FLOAD_0:
                 frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(0)));
                 break;
-            case Bytecodes.FLOAD_1        :
+            case Bytecodes.FLOAD_1:
                 frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(1)));
                 break;
-            case Bytecodes.FLOAD_2        :
+            case Bytecodes.FLOAD_2:
                 frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(2)));
                 break;
-            case Bytecodes.FLOAD_3        :
+            case Bytecodes.FLOAD_3:
                 frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(3)));
                 break;
-            case Bytecodes.DLOAD_0        :
+            case Bytecodes.DLOAD_0:
                 frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(0)));
                 break;
-            case Bytecodes.DLOAD_1        :
+            case Bytecodes.DLOAD_1:
                 frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(1)));
                 break;
-            case Bytecodes.DLOAD_2        :
+            case Bytecodes.DLOAD_2:
                 frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(2)));
                 break;
-            case Bytecodes.DLOAD_3        :
+            case Bytecodes.DLOAD_3:
                 frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(3)));
                 break;
-            case Bytecodes.ALOAD_0        :
+            case Bytecodes.ALOAD_0:
                 frame.pushObject(frame.getObject(frame.resolveLocalIndex(0)));
                 break;
-            case Bytecodes.ALOAD_1        :
+            case Bytecodes.ALOAD_1:
                 frame.pushObject(frame.getObject(frame.resolveLocalIndex(1)));
                 break;
-            case Bytecodes.ALOAD_2        :
+            case Bytecodes.ALOAD_2:
                 frame.pushObject(frame.getObject(frame.resolveLocalIndex(2)));
                 break;
-            case Bytecodes.ALOAD_3        :
+            case Bytecodes.ALOAD_3:
                 frame.pushObject(frame.getObject(frame.resolveLocalIndex(3)));
                 break;
-            case Bytecodes.IALOAD         :
-                frame.pushInt(vm.getArrayInt(frame.popInt(), frame.popObject()));
+            case Bytecodes.IALOAD:
+                frame.pushInt(runtimeInterface.getArrayInt(frame.popInt(), frame.popObject()));
                 break;
-            case Bytecodes.LALOAD         :
-                frame.pushLong(vm.getArrayLong(frame.popInt(), frame.popObject()));
+            case Bytecodes.LALOAD:
+                frame.pushLong(runtimeInterface.getArrayLong(frame.popInt(), frame.popObject()));
                 break;
-            case Bytecodes.FALOAD         :
-                frame.pushFloat(vm.getArrayFloat(frame.popInt(), frame.popObject()));
+            case Bytecodes.FALOAD:
+                frame.pushFloat(runtimeInterface.getArrayFloat(frame.popInt(), frame.popObject()));
                 break;
-            case Bytecodes.DALOAD         :
-                frame.pushDouble(vm.getArrayDouble(frame.popInt(), frame.popObject()));
+            case Bytecodes.DALOAD:
+                frame.pushDouble(runtimeInterface.getArrayDouble(frame.popInt(), frame.popObject()));
                 break;
-            case Bytecodes.AALOAD         :
-                frame.pushObject(vm.getArrayObject(frame.popInt(), frame.popObject()));
+            case Bytecodes.AALOAD:
+                frame.pushObject(runtimeInterface.getArrayObject(frame.popInt(), frame.popObject()));
                 break;
-            case Bytecodes.BALOAD         :
-                frame.pushInt(vm.getArrayByte(frame.popInt(), frame.popObject()));
+            case Bytecodes.BALOAD:
+                frame.pushInt(runtimeInterface.getArrayByte(frame.popInt(), frame.popObject()));
                 break;
-            case Bytecodes.CALOAD         :
-                frame.pushInt(vm.getArrayChar(frame.popInt(), frame.popObject()));
+            case Bytecodes.CALOAD:
+                frame.pushInt(runtimeInterface.getArrayChar(frame.popInt(), frame.popObject()));
                 break;
-             case Bytecodes.SALOAD:
-                frame.pushInt(vm.getArrayShort(frame.popInt(), frame.popObject()));
+            case Bytecodes.SALOAD:
+                frame.pushInt(runtimeInterface.getArrayShort(frame.popInt(), frame.popObject()));
                 break;
             case Bytecodes.ISTORE:
                 frame.setInt(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popInt());
                 break;
-            case Bytecodes.LSTORE         :
+            case Bytecodes.LSTORE:
                 frame.setLong(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popLong());
                 break;
-            case Bytecodes.FSTORE         :
+            case Bytecodes.FSTORE:
                 frame.setFloat(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popFloat());
                 break;
-            case Bytecodes.DSTORE         :
+            case Bytecodes.DSTORE:
                 frame.setDouble(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popDouble());
                 break;
-            case Bytecodes.ASTORE         :
+            case Bytecodes.ASTORE:
                 frame.setObject(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popObject());
                 break;
-            case Bytecodes.ISTORE_0       :
+            case Bytecodes.ISTORE_0:
                 frame.setInt(frame.resolveLocalIndex(0), frame.popInt());
                 break;
-            case Bytecodes.ISTORE_1       :
+            case Bytecodes.ISTORE_1:
                 frame.setInt(frame.resolveLocalIndex(1), frame.popInt());
                 break;
-            case Bytecodes.ISTORE_2       :
+            case Bytecodes.ISTORE_2:
                 frame.setInt(frame.resolveLocalIndex(2), frame.popInt());
                 break;
-            case Bytecodes.ISTORE_3       :
+            case Bytecodes.ISTORE_3:
                 frame.setInt(frame.resolveLocalIndex(3), frame.popInt());
                 break;
-            case Bytecodes.LSTORE_0       :
+            case Bytecodes.LSTORE_0:
                 frame.setLong(frame.resolveLocalIndex(0), frame.popLong());
                 break;
-            case Bytecodes.LSTORE_1       :
+            case Bytecodes.LSTORE_1:
                 frame.setLong(frame.resolveLocalIndex(1), frame.popLong());
                 break;
-            case Bytecodes.LSTORE_2       :
+            case Bytecodes.LSTORE_2:
                 frame.setLong(frame.resolveLocalIndex(2), frame.popLong());
                 break;
-            case Bytecodes.LSTORE_3       :
+            case Bytecodes.LSTORE_3:
                 frame.setLong(frame.resolveLocalIndex(3), frame.popLong());
                 break;
-            case Bytecodes.FSTORE_0       :
+            case Bytecodes.FSTORE_0:
                 frame.setFloat(frame.resolveLocalIndex(0), frame.popFloat());
                 break;
-            case Bytecodes.FSTORE_1       :
+            case Bytecodes.FSTORE_1:
                 frame.setFloat(frame.resolveLocalIndex(1), frame.popFloat());
                 break;
-            case Bytecodes.FSTORE_2       :
+            case Bytecodes.FSTORE_2:
                 frame.setFloat(frame.resolveLocalIndex(2), frame.popFloat());
                 break;
-            case Bytecodes.FSTORE_3       :
+            case Bytecodes.FSTORE_3:
                 frame.setFloat(frame.resolveLocalIndex(3), frame.popFloat());
                 break;
-            case Bytecodes.DSTORE_0       :
+            case Bytecodes.DSTORE_0:
                 frame.setDouble(frame.resolveLocalIndex(0), frame.popDouble());
                 break;
-            case Bytecodes.DSTORE_1       :
+            case Bytecodes.DSTORE_1:
                 frame.setDouble(frame.resolveLocalIndex(1), frame.popDouble());
                 break;
-            case Bytecodes.DSTORE_2       :
+            case Bytecodes.DSTORE_2:
                 frame.setDouble(frame.resolveLocalIndex(2), frame.popDouble());
                 break;
-            case Bytecodes.DSTORE_3       :
+            case Bytecodes.DSTORE_3:
                 frame.setDouble(frame.resolveLocalIndex(3), frame.popDouble());
                 break;
-            case Bytecodes.ASTORE_0       :
+            case Bytecodes.ASTORE_0:
                 frame.setObject(frame.resolveLocalIndex(0), frame.popObject());
                 break;
-            case Bytecodes.ASTORE_1       :
+            case Bytecodes.ASTORE_1:
                 frame.setObject(frame.resolveLocalIndex(1), frame.popObject());
                 break;
-            case Bytecodes.ASTORE_2       :
+            case Bytecodes.ASTORE_2:
                 frame.setObject(frame.resolveLocalIndex(2), frame.popObject());
                 break;
-            case Bytecodes.ASTORE_3       :
+            case Bytecodes.ASTORE_3:
                 frame.setObject(frame.resolveLocalIndex(3), frame.popObject());
                 break;
-            case Bytecodes.IASTORE        :
-                vm.setArrayInt(frame.popInt(), frame.popInt(), frame.popObject());
+            case Bytecodes.IASTORE:
+                runtimeInterface.setArrayInt(frame.popInt(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.LASTORE        :
-                vm.setArrayLong(frame.popLong(), frame.popInt(), frame.popObject());
+            case Bytecodes.LASTORE:
+                runtimeInterface.setArrayLong(frame.popLong(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.FASTORE        :
-                vm.setArrayFloat(frame.popFloat(), frame.popInt(), frame.popObject());
+            case Bytecodes.FASTORE:
+                runtimeInterface.setArrayFloat(frame.popFloat(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.DASTORE        :
-                vm.setArrayDouble(frame.popDouble(), frame.popInt(), frame.popObject());
+            case Bytecodes.DASTORE:
+                runtimeInterface.setArrayDouble(frame.popDouble(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.AASTORE        :
-                vm.setArrayObject(frame.popObject(), frame.popInt(), frame.popObject());
+            case Bytecodes.AASTORE:
+                runtimeInterface.setArrayObject(frame.popObject(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.BASTORE        :
-                vm.setArrayByte((byte) frame.popInt(), frame.popInt(), frame.popObject());
+            case Bytecodes.BASTORE:
+                runtimeInterface.setArrayByte((byte) frame.popInt(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.CASTORE        :
-                vm.setArrayChar((char) frame.popInt(), frame.popInt(), frame.popObject());
+            case Bytecodes.CASTORE:
+                runtimeInterface.setArrayChar((char) frame.popInt(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.SASTORE        :
-                vm.setArrayShort((short) frame.popInt(), frame.popInt(), frame.popObject());
+            case Bytecodes.SASTORE:
+                runtimeInterface.setArrayShort((short) frame.popInt(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.POP            :
+            case Bytecodes.POP:
                 frame.popVoid(1);
                 break;
-            case Bytecodes.POP2           :
+            case Bytecodes.POP2:
                 frame.popVoid(2);
                 break;
-            case Bytecodes.DUP            :
+            case Bytecodes.DUP:
                 frame.dup(1);
                 break;
-            case Bytecodes.DUP_X1         :
+            case Bytecodes.DUP_X1:
                 frame.dupx1();
                 break;
-            case Bytecodes.DUP_X2         :
+            case Bytecodes.DUP_X2:
                 frame.dupx2();
                 break;
-            case Bytecodes.DUP2           :
+            case Bytecodes.DUP2:
                 frame.dup(2);
                 break;
-            case Bytecodes.DUP2_X1        :
+            case Bytecodes.DUP2_X1:
                 frame.dup2x1();
                 break;
-            case Bytecodes.DUP2_X2        :
+            case Bytecodes.DUP2_X2:
                 frame.dup2x2();
                 break;
-            case Bytecodes.SWAP           :
+            case Bytecodes.SWAP:
                 frame.swapSingle();
                 break;
-            case Bytecodes.IADD           :
+            case Bytecodes.IADD:
                 frame.pushInt(frame.popInt() + frame.popInt());
                 break;
-            case Bytecodes.LADD           :
+            case Bytecodes.LADD:
                 frame.pushLong(frame.popLong() + frame.popLong());
                 break;
-            case Bytecodes.FADD           :
+            case Bytecodes.FADD:
                 frame.pushFloat(frame.popFloat() + frame.popFloat());
                 break;
-            case Bytecodes.DADD           :
+            case Bytecodes.DADD:
                 frame.pushDouble(frame.popDouble() + frame.popDouble());
                 break;
-            case Bytecodes.ISUB           :
+            case Bytecodes.ISUB:
                 frame.pushInt(-frame.popInt() + frame.popInt());
                 break;
-            case Bytecodes.LSUB           :
+            case Bytecodes.LSUB:
                 frame.pushLong(-frame.popLong() + frame.popLong());
                 break;
-            case Bytecodes.FSUB           :
+            case Bytecodes.FSUB:
                 frame.pushFloat(-frame.popFloat() + frame.popFloat());
                 break;
-            case Bytecodes.DSUB           :
+            case Bytecodes.DSUB:
                 frame.pushDouble(-frame.popDouble() + frame.popDouble());
                 break;
-            case Bytecodes.IMUL           :
+            case Bytecodes.IMUL:
                 frame.pushInt(frame.popInt() * frame.popInt());
                 break;
-            case Bytecodes.LMUL           :
+            case Bytecodes.LMUL:
                 frame.pushLong(frame.popLong() * frame.popLong());
                 break;
-            case Bytecodes.FMUL           :
+            case Bytecodes.FMUL:
                 frame.pushFloat(frame.popFloat() * frame.popFloat());
                 break;
-            case Bytecodes.DMUL           :
+            case Bytecodes.DMUL:
                 frame.pushDouble(frame.popDouble() * frame.popDouble());
                 break;
-            case Bytecodes.IDIV           :
+            case Bytecodes.IDIV:
                 divInt(frame);
                 break;
-            case Bytecodes.LDIV           :
+            case Bytecodes.LDIV:
                 divLong(frame);
                 break;
-            case Bytecodes.FDIV           :
+            case Bytecodes.FDIV:
                 divFloat(frame);
                 break;
-            case Bytecodes.DDIV           :
+            case Bytecodes.DDIV:
                 divDouble(frame);
                 break;
-            case Bytecodes.IREM           :
+            case Bytecodes.IREM:
                 remInt(frame);
                 break;
-            case Bytecodes.LREM           :
+            case Bytecodes.LREM:
                 remLong(frame);
                 break;
-            case Bytecodes.FREM           :
+            case Bytecodes.FREM:
                 remFloat(frame);
                 break;
-            case Bytecodes.DREM           :
+            case Bytecodes.DREM:
                 remDouble(frame);
                 break;
-            case Bytecodes.INEG           :
+            case Bytecodes.INEG:
                 frame.pushInt(-frame.popInt());
                 break;
-            case Bytecodes.LNEG           :
+            case Bytecodes.LNEG:
                 frame.pushLong(-frame.popLong());
                 break;
-            case Bytecodes.FNEG           :
+            case Bytecodes.FNEG:
                 frame.pushFloat(-frame.popFloat());
                 break;
-            case Bytecodes.DNEG           :
+            case Bytecodes.DNEG:
                 frame.pushDouble(-frame.popDouble());
                 break;
-            case Bytecodes.ISHL           :
+            case Bytecodes.ISHL:
                 shiftLeftInt(frame);
                 break;
-            case Bytecodes.LSHL           :
+            case Bytecodes.LSHL:
                 shiftLeftLong(frame);
                 break;
-            case Bytecodes.ISHR           :
+            case Bytecodes.ISHR:
                 shiftRightSignedInt(frame);
                 break;
-            case Bytecodes.LSHR           :
+            case Bytecodes.LSHR:
                 shiftRightSignedLong(frame);
                 break;
-            case Bytecodes.IUSHR          :
+            case Bytecodes.IUSHR:
                 shiftRightUnsignedInt(frame);
                 break;
-            case Bytecodes.LUSHR          :
+            case Bytecodes.LUSHR:
                 shiftRightUnsignedLong(frame);
                 break;
-            case Bytecodes.IAND           :
+            case Bytecodes.IAND:
                 frame.pushInt(frame.popInt() & frame.popInt());
                 break;
-            case Bytecodes.LAND           :
+            case Bytecodes.LAND:
                 frame.pushLong(frame.popLong() & frame.popLong());
                 break;
-            case Bytecodes.IOR            :
+            case Bytecodes.IOR:
                 frame.pushInt(frame.popInt() | frame.popInt());
                 break;
-            case Bytecodes.LOR            :
+            case Bytecodes.LOR:
                 frame.pushLong(frame.popLong() | frame.popLong());
                 break;
-            case Bytecodes.IXOR           :
+            case Bytecodes.IXOR:
                 frame.pushInt(frame.popInt() ^ frame.popInt());
                 break;
-            case Bytecodes.LXOR           :
+            case Bytecodes.LXOR:
                 frame.pushLong(frame.popLong() ^ frame.popLong());
                 break;
-            case Bytecodes.IINC           :
+            case Bytecodes.IINC:
                 iinc(frame, bs);
                 break;
-            case Bytecodes.I2L            :
+            case Bytecodes.I2L:
                 frame.pushLong(frame.popInt());
                 break;
-            case Bytecodes.I2F            :
+            case Bytecodes.I2F:
                 frame.pushFloat(frame.popInt());
                 break;
-            case Bytecodes.I2D            :
+            case Bytecodes.I2D:
                 frame.pushDouble(frame.popInt());
                 break;
-            case Bytecodes.L2I            :
+            case Bytecodes.L2I:
                 frame.pushInt((int) frame.popLong());
                 break;
-            case Bytecodes.L2F            :
+            case Bytecodes.L2F:
                 frame.pushFloat(frame.popLong());
                 break;
-            case Bytecodes.L2D            :
+            case Bytecodes.L2D:
                 frame.pushDouble(frame.popLong());
                 break;
-            case Bytecodes.F2I            :
+            case Bytecodes.F2I:
                 frame.pushInt((int) frame.popFloat());
                 break;
-            case Bytecodes.F2L            :
+            case Bytecodes.F2L:
                 frame.pushLong((long) frame.popFloat());
                 break;
-            case Bytecodes.F2D            :
+            case Bytecodes.F2D:
                 frame.pushDouble(frame.popFloat());
                 break;
-            case Bytecodes.D2I            :
+            case Bytecodes.D2I:
                 frame.pushInt((int) frame.popDouble());
                 break;
-            case Bytecodes.D2L            :
+            case Bytecodes.D2L:
                 frame.pushLong((long) frame.popDouble());
                 break;
-            case Bytecodes.D2F            :
+            case Bytecodes.D2F:
                 frame.pushFloat((float) frame.popDouble());
                 break;
-            case Bytecodes.I2B            :
+            case Bytecodes.I2B:
                 frame.pushInt((byte) frame.popInt());
                 break;
-            case Bytecodes.I2C            :
+            case Bytecodes.I2C:
                 frame.pushInt((char) frame.popInt());
                 break;
-            case Bytecodes.I2S            :
+            case Bytecodes.I2S:
                 frame.pushInt((short) frame.popInt());
                 break;
-            case Bytecodes.LCMP           :
+            case Bytecodes.LCMP:
                 compareLong(frame);
                 break;
-            case Bytecodes.FCMPL          :
+            case Bytecodes.FCMPL:
                 compareFloatLess(frame);
                 break;
-            case Bytecodes.FCMPG          :
+            case Bytecodes.FCMPG:
                 compareFloatGreater(frame);
                 break;
-            case Bytecodes.DCMPL          :
+            case Bytecodes.DCMPL:
                 compareDoubleLess(frame);
                 break;
-            case Bytecodes.DCMPG          :
+            case Bytecodes.DCMPG:
                 compareDoubleGreater(frame);
                 break;
-            case Bytecodes.IFEQ           :
+            case Bytecodes.IFEQ:
                 if (frame.popInt() == 0) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IFNE           :
+            case Bytecodes.IFNE:
                 if (frame.popInt() != 0) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IFLT           :
+            case Bytecodes.IFLT:
                 if (frame.popInt() < 0) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IFGE           :
+            case Bytecodes.IFGE:
                 if (frame.popInt() >= 0) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IFGT           :
+            case Bytecodes.IFGT:
                 if (frame.popInt() > 0) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IFLE           :
+            case Bytecodes.IFLE:
                 if (frame.popInt() <= 0) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ICMPEQ      :
+            case Bytecodes.IF_ICMPEQ:
                 if (frame.popInt() == frame.popInt()) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ICMPNE      :
+            case Bytecodes.IF_ICMPNE:
                 if (frame.popInt() != frame.popInt()) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ICMPLT      :
+            case Bytecodes.IF_ICMPLT:
                 if (frame.popInt() > frame.popInt()) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ICMPGE      :
+            case Bytecodes.IF_ICMPGE:
                 if (frame.popInt() <= frame.popInt()) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ICMPGT      :
+            case Bytecodes.IF_ICMPGT:
                 if (frame.popInt() < frame.popInt()) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ICMPLE      :
+            case Bytecodes.IF_ICMPLE:
                 if (frame.popInt() >= frame.popInt()) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ACMPEQ      :
+            case Bytecodes.IF_ACMPEQ:
                 if (frame.popObject() == frame.popObject()) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ACMPNE      :
+            case Bytecodes.IF_ACMPNE:
                 if (frame.popObject() != frame.popObject()) {
                     return BRANCH;
                 }
@@ -785,58 +794,58 @@
             case Bytecodes.GOTO:
             case Bytecodes.GOTO_W:
                 return BRANCH;
-            case Bytecodes.JSR            :
-            case Bytecodes.JSR_W          :
+            case Bytecodes.JSR:
+            case Bytecodes.JSR_W:
                 frame.pushInt(bs.currentBCI());
                 return BRANCH;
-            case Bytecodes.RET            :
+            case Bytecodes.RET:
                 return frame.getInt(frame.resolveLocalIndex(bs.readLocalIndex()));
-            case Bytecodes.TABLESWITCH    :
+            case Bytecodes.TABLESWITCH:
                 return tableSwitch(frame, bs);
-            case Bytecodes.LOOKUPSWITCH   :
+            case Bytecodes.LOOKUPSWITCH:
                 return lookupSwitch(frame, bs);
-            case Bytecodes.IRETURN        :
+            case Bytecodes.IRETURN:
                 frame.getParentFrame().pushInt(frame.popInt());
                 return RETURN;
-            case Bytecodes.LRETURN        :
+            case Bytecodes.LRETURN:
                 frame.getParentFrame().pushLong(frame.popLong());
                 return RETURN;
-            case Bytecodes.FRETURN        :
+            case Bytecodes.FRETURN:
                 frame.getParentFrame().pushFloat(frame.popFloat());
                 return RETURN;
-            case Bytecodes.DRETURN        :
+            case Bytecodes.DRETURN:
                 frame.getParentFrame().pushDouble(frame.popDouble());
                 return RETURN;
-            case Bytecodes.ARETURN        :
+            case Bytecodes.ARETURN:
                 frame.getParentFrame().pushObject(frame.popObject());
                 return RETURN;
-            case Bytecodes.RETURN         :
+            case Bytecodes.RETURN:
                 return RETURN;
-            case Bytecodes.GETSTATIC      :
+            case Bytecodes.GETSTATIC:
                 getField(frame, null, bs.currentBC(), bs.readCPI());
                 break;
-            case Bytecodes.PUTSTATIC      :
+            case Bytecodes.PUTSTATIC:
                 putStatic(frame, bs.readCPI());
                 break;
             case Bytecodes.GETFIELD:
                 getField(frame, nullCheck(frame.popObject()), bs.currentBC(), bs.readCPI());
                 break;
-            case Bytecodes.PUTFIELD       :
+            case Bytecodes.PUTFIELD:
                 putField(frame, bs.readCPI());
                 break;
-            case Bytecodes.INVOKEVIRTUAL  :
+            case Bytecodes.INVOKEVIRTUAL:
                 callFrame = invokeVirtual(frame, bs.readCPI());
                 if (callFrame == null) {
                     break;
                 }
                 return CALL;
-            case Bytecodes.INVOKESPECIAL  :
+            case Bytecodes.INVOKESPECIAL:
                 callFrame = invokeSpecial(frame, bs.readCPI());
                 if (callFrame == null) {
                     break;
                 }
                 return CALL;
-            case Bytecodes.INVOKESTATIC   :
+            case Bytecodes.INVOKESTATIC:
                 callFrame = invokeStatic(frame, bs.readCPI());
                 if (callFrame == null) {
                     break;
@@ -848,53 +857,57 @@
                     break;
                 }
                 return CALL;
-            case Bytecodes.XXXUNUSEDXXX   :
-                assert false : "unused bytecode used. behaviour unspecfied.";
+            case Bytecodes.XXXUNUSEDXXX:
+                assert false : "unused bytecode used. behaviour unspecified.";
                 // nop
                 break;
-            case Bytecodes.NEW            :
+            case Bytecodes.NEW:
                 frame.pushObject(allocateInstance(frame, bs.readCPI()));
                 break;
-            case Bytecodes.NEWARRAY       :
+            case Bytecodes.NEWARRAY:
                 frame.pushObject(allocateNativeArray(frame, bs.readByte()));
                 break;
-            case Bytecodes.ANEWARRAY      :
+            case Bytecodes.ANEWARRAY:
                 frame.pushObject(allocateArray(frame, bs.readCPI()));
                 break;
-            case Bytecodes.ARRAYLENGTH    :
+            case Bytecodes.ARRAYLENGTH:
                 frame.pushInt(Array.getLength(nullCheck(frame.popObject())));
                 break;
-            case Bytecodes.ATHROW         :
-                throw (Throwable) frame.popObject();
-            case Bytecodes.CHECKCAST      :
+            case Bytecodes.ATHROW:
+                Throwable t = (Throwable) frame.popObject();
+                if ("break".equals(t.getMessage())) {
+                    t.printStackTrace();
+                }
+                throw t;
+            case Bytecodes.CHECKCAST:
                 checkCast(frame, bs.readCPI());
                 break;
-            case Bytecodes.INSTANCEOF     :
+            case Bytecodes.INSTANCEOF:
                 instanceOf(frame, bs.readCPI());
                 break;
-            case Bytecodes.MONITORENTER   :
-                vm.monitorEnter(frame.popObject());
+            case Bytecodes.MONITORENTER:
+                runtimeInterface.monitorEnter(frame.popObject());
                 break;
-            case Bytecodes.MONITOREXIT    :
-                vm.monitorExit(frame.popObject());
+            case Bytecodes.MONITOREXIT:
+                runtimeInterface.monitorExit(frame.popObject());
                 break;
-            case Bytecodes.WIDE           :
+            case Bytecodes.WIDE:
                 assert false;
                 break;
-            case Bytecodes.MULTIANEWARRAY :
+            case Bytecodes.MULTIANEWARRAY:
                 frame.pushObject(allocateMultiArray(frame, bs.readCPI(), bs.readUByte(bs.currentBCI() + 3)));
                 break;
-            case Bytecodes.IFNULL         :
+            case Bytecodes.IFNULL:
                 if (frame.popObject() == null) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IFNONNULL      :
+            case Bytecodes.IFNONNULL:
                 if (frame.popObject() != null) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.BREAKPOINT     :
+            case Bytecodes.BREAKPOINT:
                 assert false : "no breakpoints supported at this time.";
                 break; // nop
         }
@@ -912,11 +925,6 @@
                 currentFrame = popFrame(currentFrame);
             } else {
                 // found a handler -> execute it
-                if (handler.isCatchAll()) {
-                    catchAllExceptionHandler = handler;
-                } else {
-                    catchAllExceptionHandler = null;
-                }
                 currentFrame.setBCI(handler.handlerBCI());
                 currentFrame.popStack();
                 currentFrame.pushObject(t);
@@ -938,13 +946,12 @@
         }
     }
 
-
     private void setStackTrace(InterpreterFrame frame, Throwable t, StackTraceElement[] stackTrace) {
-      vm.setField(stackTrace, t,  findThrowableField(frame, "stackTrace"));
+        runtimeInterface.setFieldObject(stackTrace, t, findThrowableField(frame, "stackTrace"));
     }
 
     private StackTraceElement[] getBackTrace(InterpreterFrame frame, Throwable t) {
-        Object value = vm.getField(t, findThrowableField(frame, "backtrace"));
+        Object value = runtimeInterface.getFieldObject(t, findThrowableField(frame, "backtrace"));
         if (value instanceof StackTraceElement[]) {
             return (StackTraceElement[]) value;
         }
@@ -952,25 +959,23 @@
     }
 
     private void setBackTrace(InterpreterFrame frame, Throwable t, StackTraceElement[] backtrace) {
-        vm.setField(backtrace, t, findThrowableField(frame, "backtrace"));
+        runtimeInterface.setFieldObject(backtrace, t, findThrowableField(frame, "backtrace"));
     }
 
     private ExceptionHandler resolveExceptionHandlers(InterpreterFrame frame, int bci, Throwable t) {
         ExceptionHandler[] handlers = frame.getMethod().exceptionHandlers();
         for (int i = 0; i < handlers.length; i++) {
             ExceptionHandler handler = handlers[i];
-            if (bci >= handler.startBCI()
-                            && bci <= handler.endBCI()
-                            && (catchAllExceptionHandler == null || !handler.isCatchAll())) {
+            if (bci >= handler.startBCI() && bci <= handler.endBCI()) {
                 ResolvedJavaType catchType = null;
                 if (!handler.isCatchAll()) {
-                    catchType = resolveType(frame, bci, (char) handler.catchTypeCPI());
+                    // exception handlers are similar to instanceof bytecodes, so we pass instanceof
+                    catchType = resolveType(frame, Bytecodes.INSTANCEOF, (char) handler.catchTypeCPI());
                 }
 
-                if (catchType == null
-                                || catchType.toJava().isInstance(t)) {
+                if (catchType == null || catchType.toJava().isInstance(t)) {
                     // the first found exception handler is our exception handler
-                   return handler;
+                    return handler;
                 }
             }
         }
@@ -979,8 +984,6 @@
 
     private InterpreterFrame allocateFrame(InterpreterFrame frame, BytecodeStream bs) {
         try {
-            stackFrameDepth++;
-
             InterpreterFrame nextFrame = this.callFrame;
 
             assert nextFrame != null;
@@ -994,58 +997,53 @@
             }
             if (Modifier.isSynchronized(nextFrame.getMethod().accessFlags())) {
                 if (TRACE) {
-                    traceOp("Method monitor enter");
+                    traceOp(frame, "Method monitor enter");
                 }
                 if (Modifier.isStatic(nextFrame.getMethod().accessFlags())) {
-                    vm.monitorEnter(nextFrame.getMethod().holder().toJava());
+                    runtimeInterface.monitorEnter(nextFrame.getMethod().holder().toJava());
                 } else {
                     Object enterObject = nextFrame.getObject(frame.resolveLocalIndex(0));
                     assert enterObject != null;
-                    vm.monitorEnter(enterObject);
+                    runtimeInterface.monitorEnter(enterObject);
                 }
             }
 
             return nextFrame;
         } finally {
-            // catch all exception handlers are not allowed to call any method anyway.
-            catchAllExceptionHandler = null;
             callFrame = null;
             bs.next();
         }
     }
 
     private InterpreterFrame popFrame(InterpreterFrame frame) {
-        catchAllExceptionHandler = null;
         InterpreterFrame parent = frame.getParentFrame();
         if (Modifier.isSynchronized(frame.getMethod().accessFlags())) {
             if (TRACE) {
-                traceOp("Method monitor exit");
+                traceOp(frame, "Method monitor exit");
             }
             if (Modifier.isStatic(frame.getMethod().accessFlags())) {
-                vm.monitorExit(frame.getMethod().holder().toJava());
+                runtimeInterface.monitorExit(frame.getMethod().holder().toJava());
             } else {
                 Object exitObject = frame.getObject(frame.resolveLocalIndex(0));
                 if (exitObject != null) {
-                    vm.monitorExit(exitObject);
+                    runtimeInterface.monitorExit(exitObject);
                 }
             }
         }
         if (TRACE) {
             traceCall(frame, "Ret");
         }
-        stackFrameDepth--;
 
         frame.dispose();
         return parent;
     }
 
-    private void traceOp(String opName) {
-        trace(stackFrameDepth + 1, opName);
+    private void traceOp(InterpreterFrame frame, String opName) {
+        trace(frame.depth(), opName);
     }
 
     private void traceCall(InterpreterFrame frame, String type) {
-        trace(stackFrameDepth, type + " " +
-                        frame.getMethod() + " - " + frame.getMethod().signature().asString());
+        trace(frame.depth(), type + " " + frame.getMethod() + " - " + frame.getMethod().signature().asString());
     }
 
     private void trace(int level, String message) {
@@ -1057,7 +1055,6 @@
         System.out.println(builder);
     }
 
-
     private void divInt(InterpreterFrame frame) {
         int dividend = frame.popInt();
         int divisor = frame.popInt();
@@ -1082,7 +1079,6 @@
         frame.pushDouble(divisor / dividend);
     }
 
-
     private void remInt(InterpreterFrame frame) {
         int dividend = frame.popInt();
         int divisor = frame.popInt();
@@ -1144,8 +1140,7 @@
     }
 
     private int lookupSwitch(InterpreterFrame frame, BytecodeStream bs) {
-        return lookupSearch(
-                        new BytecodeLookupSwitch(bs, bs.currentBCI()), frame.popInt());
+        return lookupSearch(new BytecodeLookupSwitch(bs, bs.currentBCI()), frame.popInt());
     }
 
     /**
@@ -1166,7 +1161,7 @@
                 return switchHelper.bci() + switchHelper.offsetAt(mid); // key found
             }
         }
-        return switchHelper.defaultTarget();  // key not found.
+        return switchHelper.defaultTarget(); // key not found.
     }
 
     private int tableSwitch(InterpreterFrame frame, BytecodeStream bs) {
@@ -1195,8 +1190,8 @@
         return constantPool.lookupType(cpi, opcode).resolve(frame.getMethod().holder());
     }
 
-    private ResolvedJavaType resolveType(InterpreterFrame frame, Class<?> javaClass) {
-        return vm.getRuntime().getResolvedJavaType(javaClass).resolve(frame.getMethod().holder());
+    private ResolvedJavaType resolveType(InterpreterFrame frame, Class< ? > javaClass) {
+        return metaAccessProvider.getResolvedJavaType(javaClass).resolve(frame.getMethod().holder());
     }
 
     private ResolvedJavaMethod resolveMethod(InterpreterFrame frame, int opcode, char cpi) {
@@ -1212,9 +1207,7 @@
     }
 
     private void instanceOf(InterpreterFrame frame, char cpi) {
-        frame.pushInt(resolveType(frame, Bytecodes.INSTANCEOF, cpi).
-                        toJava().isInstance(frame.popObject())
-                        ? 1 : 0);
+        frame.pushInt(resolveType(frame, Bytecodes.INSTANCEOF, cpi).toJava().isInstance(frame.popObject()) ? 1 : 0);
     }
 
     private void pushCPConstant(InterpreterFrame frame, char cpi) {
@@ -1224,7 +1217,7 @@
         if (constant instanceof Constant) {
             Constant c = ((Constant) constant);
             switch (c.kind) {
-                case Int :
+                case Int:
                     frame.pushInt(c.asInt());
                     break;
                 case Float:
@@ -1233,10 +1226,10 @@
                 case Object:
                     frame.pushObject(c.asObject());
                     break;
-                case Double :
+                case Double:
                     frame.pushDouble(c.asDouble());
                     break;
-                case Long :
+                case Long:
                     frame.pushLong(c.asLong());
                     break;
                 default:
@@ -1285,6 +1278,7 @@
         }
         return value;
     }
+
     private InterpreterFrame invokeStatic(InterpreterFrame frame, char cpi) throws Throwable {
         return invoke(frame, resolveMethod(frame, Bytecodes.INVOKESTATIC, cpi), null);
     }
@@ -1319,104 +1313,91 @@
         return invoke(frame, m, nullCheck(frame.peekReceiver(m)));
     }
 
-    private void invokeReflective(InterpreterFrame frame, ResolvedJavaMethod method, boolean hasReceiver) throws Throwable {
-        Class<?>[] parameterTypes = resolveMethodArguments(method);
-        Object[] parameters = popArgumentsAsObject(frame, method);
-        Class<?> javaClass = method.holder().toJava();
-
-        Object parentObject = null;
-        if (hasReceiver) {
-            parentObject = frame.popObject();
-            nullCheck(parentObject);
-        }
-        Object returnValue = null;
+    private Object[] popArgumentsAsObject(InterpreterFrame frame, ResolvedJavaMethod method, boolean hasReceiver) {
+        Signature signature = method.signature();
+        int argumentCount = method.signature().argumentCount(hasReceiver);
+        Object[] parameters = new Object[argumentCount];
 
-        if (redirect(method)) {
-            if (TRACE) {
-                traceCall(frame, "Delegate " + method);
-            }
-            try {
-                returnValue = methodDelegates.get(method).invoke(frame, method, parentObject, parameters);
-            } catch (Throwable e) {
-                throw e;
-            }
-        } else {
-            if (TRACE) {
-                traceCall(frame, "Reflective " + method);
-            }
-            try {
-                Method javaMethod = javaClass.getDeclaredMethod(method.name(), parameterTypes);
-                javaMethod.setAccessible(true);
-                returnValue = javaMethod.invoke(parentObject, parameters);
-            } catch (InvocationTargetException e) {
-                e.printStackTrace(System.out);
-                throw e.getTargetException();
-            } catch (NoSuchMethodException | SecurityException e) {
-                throw new AbstractMethodError();
-            }
+        int lastSignatureIndex = hasReceiver ? 1 : 0;
+        for (int i = argumentCount - 1; i >= lastSignatureIndex; i--) {
+            ResolvedJavaType type = signature.argumentTypeAt(i - lastSignatureIndex, method.holder()).resolve(method.holder());
+            parameters[i] = popAsObject(frame, type.kind());
         }
 
-        pushAsObject(frame, method.signature().returnKind(), returnValue);
-    }
-
-    private Object[] popArgumentsAsObject(InterpreterFrame frame, ResolvedJavaMethod method) {
-        Signature signature = method.signature();
-        int argumentCount = method.signature().argumentCount(false);
-        Object[] parameters = new Object[argumentCount];
-        for (int i = argumentCount - 1; i >= 0; i--) {
-            ResolvedJavaType type = signature.argumentTypeAt(i, method.holder()).resolve(method.holder());
-            parameters[i] =  popAsObject(frame, type.kind());
+        if (hasReceiver) {
+            parameters[0] = frame.popObject();
         }
         return parameters;
     }
 
-    private Class<?>[] resolveMethodArguments(ResolvedJavaMethod method) {
-        Signature signature = method.signature();
-        int argumentCount = signature.argumentCount(false);
-        Class<?>[] parameterTypes = new Class[argumentCount];
-
-        for (int i = 0; i < argumentCount; i++) {
-            JavaType type = signature.argumentTypeAt(i, method.holder());
-            ResolvedJavaType resolvedType = type.resolve(method.holder());
-            parameterTypes[i] = resolvedType.toJava();
-        }
-        return parameterTypes;
-    }
-
-    private InterpreterFrame invoke(InterpreterFrame parent, ResolvedJavaMethod method, Object receiver) throws Throwable {
-        if (stackFrameDepth >= maxStackFrames) {
+    private InterpreterFrame invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object receiver) throws Throwable {
+        if (caller.depth() >= maxStackFrames) {
             throw new StackOverflowError("Maximum callstack of " + maxStackFrames + " exceeded.");
         }
-        if (redirect(method)) {
-            invokeReflective(parent, method, receiver != null);
 
-            // returning null results in a jump to the next instruction
-            // since the method is already successfully invoked.
-            return null;
+        if (Modifier.isNative(method.accessFlags())) {
+            return invokeNativeMethodViaVM(caller, method, receiver != null);
         } else {
-            if (Modifier.isNative(method.accessFlags())) {
-                invokeReflective(parent, method, receiver != null);
-                return null;
+            MethodRedirectionInfo redirectedMethod = methodDelegates.get(method);
+            if (redirectedMethod != null) {
+                return invokeRedirectedMethodViaVM(caller, method, redirectedMethod, receiver != null);
             } else {
-                return parent.create(method, receiver != null);
+                return invokeOptimized(caller, method, receiver != null);
             }
         }
     }
 
-    private boolean redirect(ResolvedJavaMethod method) {
-        return methodDelegates.containsKey(method);
+    private InterpreterFrame invokeNativeMethodViaVM(InterpreterFrame caller, ResolvedJavaMethod method, boolean hasReceiver) throws Throwable {
+        assert !methodDelegates.containsKey(method) : "must not be redirected";
+        if (TRACE) {
+            traceCall(caller, "Native " + method);
+        }
+
+        // mark the current thread as high level and execute the native method
+        Object[] parameters = popArgumentsAsObject(caller, method, hasReceiver);
+        Object returnValue = runtimeInterface.invoke(method, parameters);
+        pushAsObject(caller, method.signature().returnKind(), returnValue);
+
+        return null;
     }
 
+    private InterpreterFrame invokeRedirectedMethodViaVM(InterpreterFrame caller, ResolvedJavaMethod originalMethod, MethodRedirectionInfo redirectionInfo, boolean hasReceiver) throws Throwable {
+        assert methodDelegates.containsKey(originalMethod) : "must be redirected";
+        if (TRACE) {
+            traceCall(caller, "Delegate " + originalMethod);
+        }
+
+        // current thread is low level and we also execute the target method in the low-level interpreter
+        Object[] originalCalleeParameters = popArgumentsAsObject(caller, originalMethod, hasReceiver);
+        Object[] parameters = new Object[]{caller, originalMethod, originalCalleeParameters};
+        Object returnValue = redirectionInfo.getTargetMethod().invoke(redirectionInfo.getReceiver(), parameters);
+        pushAsObject(caller, originalMethod.signature().returnKind(), returnValue);
+
+        return null;
+    }
+
+    private InterpreterFrame invokeOptimized(InterpreterFrame parent, ResolvedJavaMethod method, boolean hasReceiver) throws Throwable {
+        return parent.create(method, hasReceiver);
+    }
 
     private Object allocateMultiArray(InterpreterFrame frame, char cpi, int dimension) {
-        ResolvedJavaType type = resolveType(frame, Bytecodes.MULTIANEWARRAY, cpi);
+        ResolvedJavaType type = getLastDimensionType(resolveType(frame, Bytecodes.MULTIANEWARRAY, cpi));
+
         int[] dimensions = new int[dimension];
-        for (int i = 0; i < dimension; i++) {
+        for (int i = dimension - 1; i >= 0; i--) {
             dimensions[i] = frame.popInt();
         }
         return Array.newInstance(type.toJava(), dimensions);
     }
 
+    private ResolvedJavaType getLastDimensionType(ResolvedJavaType type) {
+        ResolvedJavaType result = type;
+        while (result.isArrayClass()) {
+            result = result.componentType();
+        }
+        return result;
+    }
+
     private Object allocateArray(InterpreterFrame frame, char cpi) {
         ResolvedJavaType type = resolveType(frame, Bytecodes.ANEWARRAY, cpi);
         return Array.newInstance(type.toJava(), frame.popInt());
@@ -1425,21 +1406,21 @@
     private Object allocateNativeArray(InterpreterFrame frame, byte cpi) {
         // the constants for the cpi are loosely defined and no real cpi indices.
         switch (cpi) {
-            case 4 :
+            case 4:
                 return new byte[frame.popInt()];
-            case 8 :
+            case 8:
                 return new byte[frame.popInt()];
-            case 5 :
+            case 5:
                 return new char[frame.popInt()];
-            case 7 :
+            case 7:
                 return new double[frame.popInt()];
-            case 6 :
+            case 6:
                 return new float[frame.popInt()];
-            case 10 :
+            case 10:
                 return new int[frame.popInt()];
-            case 11 :
+            case 11:
                 return new long[frame.popInt()];
-            case 9 :
+            case 9:
                 return new short[frame.popInt()];
             default:
                 assert false : "unexpected case";
@@ -1448,7 +1429,7 @@
     }
 
     private Object allocateInstance(InterpreterFrame frame, char cpi) throws InstantiationException {
-        return vm.newObject(resolveType(frame, Bytecodes.NEW, cpi));
+        return runtimeInterface.newObject(resolveType(frame, Bytecodes.NEW, cpi));
     }
 
     private void iinc(InterpreterFrame frame, BytecodeStream bs) {
@@ -1466,52 +1447,52 @@
 
     private void putFieldStatic(InterpreterFrame frame, ResolvedJavaField field) {
         switch (field.kind()) {
-            case Boolean :
-            case Byte :
-            case Char :
-            case Short :
-            case Int :
-                vm.setFieldInt(frame.popInt(), null, field);
+            case Boolean:
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+                runtimeInterface.setFieldInt(frame.popInt(), null, field);
                 break;
-            case Double :
-                vm.setFieldDouble(frame.popDouble(), null, field);
+            case Double:
+                runtimeInterface.setFieldDouble(frame.popDouble(), null, field);
                 break;
-            case Float :
-                vm.setFieldFloat(frame.popFloat(), null, field);
+            case Float:
+                runtimeInterface.setFieldFloat(frame.popFloat(), null, field);
                 break;
-            case Long :
-                vm.setFieldLong(frame.popLong(), null, field);
+            case Long:
+                runtimeInterface.setFieldLong(frame.popLong(), null, field);
                 break;
-            case Object :
-                vm.setField(frame.popObject(), null, field);
+            case Object:
+                runtimeInterface.setFieldObject(frame.popObject(), null, field);
                 break;
-            default :
+            default:
                 assert false : "unexpected case";
         }
     }
 
     private void putFieldVirtual(InterpreterFrame frame, ResolvedJavaField field) {
         switch (field.kind()) {
-            case Boolean :
-            case Byte :
-            case Char :
-            case Short :
-            case Int :
-                vm.setFieldInt(frame.popInt(), nullCheck(frame.popObject()), field);
+            case Boolean:
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+                runtimeInterface.setFieldInt(frame.popInt(), nullCheck(frame.popObject()), field);
                 break;
-            case Double :
-                vm.setFieldDouble(frame.popDouble(), nullCheck(frame.popObject()), field);
+            case Double:
+                runtimeInterface.setFieldDouble(frame.popDouble(), nullCheck(frame.popObject()), field);
                 break;
-            case Float :
-                vm.setFieldFloat(frame.popFloat(), nullCheck(frame.popObject()), field);
+            case Float:
+                runtimeInterface.setFieldFloat(frame.popFloat(), nullCheck(frame.popObject()), field);
                 break;
-            case Long :
-                vm.setFieldLong(frame.popLong(), nullCheck(frame.popObject()), field);
+            case Long:
+                runtimeInterface.setFieldLong(frame.popLong(), nullCheck(frame.popObject()), field);
                 break;
-            case Object :
-                vm.setField(frame.popObject(), nullCheck(frame.popObject()), field);
+            case Object:
+                runtimeInterface.setFieldObject(frame.popObject(), nullCheck(frame.popObject()), field);
                 break;
-            default :
+            default:
                 assert false : "unexpected case";
         }
     }
@@ -1519,63 +1500,70 @@
     private void getField(InterpreterFrame frame, Object base, int opcode, char cpi) {
         ResolvedJavaField field = resolveField(frame, opcode, cpi);
         switch (field.kind()) {
-            case Boolean :
-            case Byte :
-            case Char :
-            case Short :
-            case Int :
-                frame.pushInt(vm.getFieldInt(base, field));
+            case Boolean:
+                frame.pushInt(runtimeInterface.getFieldBoolean(base, field) ? 1 : 0);
+                break;
+            case Byte:
+                frame.pushInt(runtimeInterface.getFieldByte(base, field));
                 break;
-            case Double :
-                frame.pushDouble(vm.getFieldDouble(base, field));
+            case Char:
+                frame.pushInt(runtimeInterface.getFieldChar(base, field));
+                break;
+            case Short:
+                frame.pushInt(runtimeInterface.getFieldShort(base, field));
                 break;
-            case Float :
-                frame.pushFloat(vm.getFieldFloat(base, field));
+            case Int:
+                frame.pushInt(runtimeInterface.getFieldInt(base, field));
+                break;
+            case Double:
+                frame.pushDouble(runtimeInterface.getFieldDouble(base, field));
                 break;
-            case Long :
-                frame.pushLong(vm.getFieldLong(base, field));
+            case Float:
+                frame.pushFloat(runtimeInterface.getFieldFloat(base, field));
                 break;
-            case Object :
-                frame.pushObject(vm.getField(base, field));
+            case Long:
+                frame.pushLong(runtimeInterface.getFieldLong(base, field));
                 break;
-            default :
+            case Object:
+                frame.pushObject(runtimeInterface.getFieldObject(base, field));
+                break;
+            default:
                 assert false : "unexpected case";
         }
     }
 
-
     private int pushAsObject(InterpreterFrame frame, Kind typeKind, Object value) {
-        switch(typeKind) {
-            case Int :
+        switch (typeKind) {
+            case Int:
                 frame.pushInt((int) value);
                 break;
-            case Long :
+            case Long:
                 frame.pushLong((long) value);
                 return 2;
-            case Boolean :
+            case Boolean:
                 frame.pushInt(((boolean) value) ? 1 : 0);
                 break;
-            case Byte :
+            case Byte:
                 frame.pushInt((byte) value);
                 break;
-            case Char :
+            case Char:
                 frame.pushInt((char) value);
                 break;
-            case Double :
+            case Double:
                 frame.pushDouble((double) value);
                 return 2;
-            case Float :
+            case Float:
                 frame.pushFloat((float) value);
                 break;
-            case Short :
+            case Short:
                 frame.pushInt((short) value);
                 break;
-            case Object :
+            case Object:
                 frame.pushObject(value);
                 break;
-            case Void :
+            case Void:
                 return 0;
-            default :
+            default:
                 assert false : "case not specified";
         }
         return 1;
@@ -1583,27 +1571,27 @@
 
     private Object popAsObject(InterpreterFrame frame, Kind typeKind) {
         switch (typeKind) {
-            case Boolean :
+            case Boolean:
                 return frame.popInt() == 1 ? true : false;
-            case Byte :
+            case Byte:
                 return (byte) frame.popInt();
-            case Char :
+            case Char:
                 return (char) frame.popInt();
-            case Double :
+            case Double:
                 return frame.popDouble();
-            case Int :
+            case Int:
                 return frame.popInt();
-            case Float :
+            case Float:
                 return frame.popFloat();
-            case Long :
+            case Long:
                 return frame.popLong();
-            case Short :
+            case Short:
                 return (short) frame.popInt();
-            case Object :
+            case Object:
                 return frame.popObject();
-            case Void :
+            case Void:
                 return null;
-            default :
+            default:
                 assert false : "unexpected case";
         }
         return null;
@@ -1611,13 +1599,13 @@
 
     private ResolvedJavaMethod resolveRootMethod() {
         try {
-            return vm.getRuntime().getResolvedJavaMethod(BytecodeInterpreter.class.getDeclaredMethod("execute", Method.class, Object[].class));
+            return metaAccessProvider.getResolvedJavaMethod(BytecodeInterpreter.class.getDeclaredMethod("execute", Method.class, Object[].class));
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
     }
 
-    private static Method findMethod(Class<?> clazz, String name, Class<?> ... parameters) {
+    private static Method findMethod(Class< ? > clazz, String name, Class< ? >... parameters) {
         try {
             return clazz.getDeclaredMethod(name, parameters);
         } catch (Exception e) {
@@ -1655,4 +1643,32 @@
         return null;
     }
 
+    private class MethodRedirectionInfo {
+
+        private InterpreterCallable receiver;
+        private Method method;
+
+        public MethodRedirectionInfo(InterpreterCallable instance) {
+            this.receiver = instance;
+            this.method = resolveMethod(instance);
+        }
+
+        public InterpreterCallable getReceiver() {
+            return receiver;
+        }
+
+        public Method getTargetMethod() {
+            return method;
+        }
+
+        private Method resolveMethod(InterpreterCallable instance) {
+            try {
+                return instance.getClass().getMethod(InterpreterCallable.INTERPRETER_CALLABLE_INVOKE_NAME, InterpreterCallable.INTERPRETER_CALLABLE_INVOKE_SIGNATURE);
+            } catch (NoSuchMethodException e) {
+                throw new InterpreterException(e);
+            } catch (SecurityException e) {
+                throw new InterpreterException(e);
+            }
+        }
+    }
 }
--- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterCallable.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterCallable.java	Thu Jul 05 16:54:45 2012 +0200
@@ -26,7 +26,10 @@
 
 
 public interface InterpreterCallable {
+    // static final fields
+    String INTERPRETER_CALLABLE_INVOKE_NAME = "invoke";
+    Class<?>[] INTERPRETER_CALLABLE_INVOKE_SIGNATURE = {InterpreterFrame.class, ResolvedJavaMethod.class, Object[].class};
 
-    Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object base, Object[] arguments) throws Throwable;
-
+    // methods
+    Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable;
 }
--- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterFrame.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterFrame.java	Thu Jul 05 16:54:45 2012 +0200
@@ -37,21 +37,23 @@
     private static final int SINGLE = 1;
 
     /** Pointer to the top-most stack frame element. */
+    private int depth;
     private int tos;
 
     public InterpreterFrame(ResolvedJavaMethod method, int additionalStackSpace) {
-        this(method, null, additionalStackSpace);
+        this(method, null, additionalStackSpace, 0);
     }
 
-    private InterpreterFrame(ResolvedJavaMethod method, InterpreterFrame parent, int additionalStackSpace) {
+    private InterpreterFrame(ResolvedJavaMethod method, InterpreterFrame parent, int additionalStackSpace, int depth) {
         super(method.maxLocals() + method.maxStackSize() + BASE_LENGTH + additionalStackSpace, parent);
         setMethod(method);
         setBCI(0);
+        this.depth = depth;
         this.tos = BASE_LENGTH;
     }
 
     public InterpreterFrame create(ResolvedJavaMethod method, boolean hasReceiver) {
-        InterpreterFrame frame = new InterpreterFrame(method, this, 0);
+        InterpreterFrame frame = new InterpreterFrame(method, this, 0, this.depth + 1);
         int length = method.signature().argumentSlots(hasReceiver);
 
         frame.pushVoid(method.maxLocals());
@@ -67,6 +69,10 @@
         return BASE_LENGTH + index;
     }
 
+    public int depth() {
+        return depth;
+    }
+
     private int stackTos() {
         return BASE_LENGTH + getMethod().maxLocals();
     }
@@ -245,6 +251,7 @@
     }
 
     private void decrementTos(int size) {
+        assert tos - size >= stackTos();
         tos -= size;
     }
 
--- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/VMAdapter.java	Thu Jul 05 16:54:00 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,313 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.interpreter;
-
-import java.lang.reflect.*;
-
-import sun.misc.*;
-
-import com.oracle.graal.api.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.hotspot.meta.*;
-
-
-/**
- * This class encapsulates all vm specific methods for the {@link BytecodeInterpreter}.
- */
-public class VMAdapter {
-
-    private static final Unsafe unsafe = loadUnsafe();
-
-    protected VMAdapter() {
-    }
-
-    public MetaAccessProvider getRuntime() {
-        return Graal.getRuntime().getCapability(MetaAccessProvider.class);
-    }
-
-    public void monitorEnter(Object value) {
-        nullCheck(value);
-        unsafe.monitorEnter(value);
-    }
-
-    public void monitorExit(Object value) {
-        nullCheck(value);
-        unsafe.monitorExit(value);
-    }
-
-    public Object newObject(ResolvedJavaType type) throws InstantiationException {
-        return unsafe.allocateInstance(type.toJava());
-    }
-
-    public Object getField(Object base, ResolvedJavaField field) {
-        long offset = resolveOffset(field);
-        if (isVolatile(field)) {
-            return unsafe.getObjectVolatile(resolveBase(base, field), offset);
-        } else {
-            return unsafe.getObject(resolveBase(base, field), offset);
-        }
-    }
-
-    public int getFieldInt(Object base, ResolvedJavaField field) {
-        long offset = resolveOffset(field);
-        if (isVolatile(field)) {
-            return unsafe.getIntVolatile(resolveBase(base, field), offset);
-        } else {
-            return unsafe.getInt(resolveBase(base, field), offset);
-        }
-    }
-
-    public long getFieldLong(Object base, ResolvedJavaField field) {
-        long offset = resolveOffset(field);
-        if (isVolatile(field)) {
-            return unsafe.getLongVolatile(resolveBase(base, field), offset);
-        } else {
-            return unsafe.getLong(resolveBase(base, field), offset);
-        }
-    }
-
-    public double getFieldDouble(Object base, ResolvedJavaField field) {
-        long offset = resolveOffset(field);
-        if (isVolatile(field)) {
-            return unsafe.getDoubleVolatile(resolveBase(base, field), offset);
-        } else {
-            return unsafe.getDouble(resolveBase(base, field), offset);
-        }
-    }
-
-    public float getFieldFloat(Object base, ResolvedJavaField field) {
-        long offset = resolveOffset(field);
-        if (isVolatile(field)) {
-            return unsafe.getFloatVolatile(resolveBase(base, field), offset);
-        } else {
-            return unsafe.getFloat(resolveBase(base, field), offset);
-        }
-    }
-
-    public void setField(Object value, Object base, ResolvedJavaField field) {
-        long offset = resolveOffset(field);
-        if (isVolatile(field)) {
-            unsafe.putObjectVolatile(resolveBase(base, field), offset, value);
-        } else {
-            unsafe.putObject(resolveBase(base, field), offset, value);
-        }
-    }
-
-    public void setFieldInt(int value, Object base, ResolvedJavaField field) {
-        long offset = resolveOffset(field);
-        if (isVolatile(field)) {
-            unsafe.putIntVolatile(resolveBase(base, field), offset, value);
-        } else {
-            unsafe.putInt(resolveBase(base, field), offset, value);
-        }
-    }
-
-
-    public void setFieldFloat(float value, Object base, ResolvedJavaField field) {
-        long offset = resolveOffset(field);
-        if (isVolatile(field)) {
-            unsafe.putFloatVolatile(resolveBase(base, field), offset, value);
-        } else {
-            unsafe.putFloat(resolveBase(base, field), offset, value);
-        }
-    }
-
-    public void setFieldDouble(double value, Object base, ResolvedJavaField field) {
-        long offset = resolveOffset(field);
-        if (isVolatile(field)) {
-            unsafe.putDoubleVolatile(resolveBase(base, field), offset, value);
-        } else {
-            unsafe.putDouble(resolveBase(base, field), offset, value);
-        }
-    }
-
-    public void setFieldLong(long value, Object base, ResolvedJavaField field) {
-        long offset = resolveOffset(field);
-        if (isVolatile(field)) {
-            unsafe.putDoubleVolatile(resolveBase(base, field), offset, value);
-        } else {
-            unsafe.putDouble(resolveBase(base, field), offset, value);
-        }
-    }
-
-    public byte getArrayByte(long index, Object array) {
-        checkArray(array, index);
-        return unsafe.getByte(array, Unsafe.ARRAY_BYTE_BASE_OFFSET + Unsafe.ARRAY_BYTE_INDEX_SCALE * index);
-    }
-
-    public char getArrayChar(long index, Object array) {
-        checkArray(array, index);
-        return unsafe.getChar(array, Unsafe.ARRAY_CHAR_BASE_OFFSET + Unsafe.ARRAY_CHAR_INDEX_SCALE * index);
-    }
-
-    public short getArrayShort(long index, Object array) {
-        checkArray(array, index);
-        return unsafe.getShort(array, Unsafe.ARRAY_SHORT_BASE_OFFSET + Unsafe.ARRAY_SHORT_INDEX_SCALE * index);
-    }
-
-    public int getArrayInt(long index, Object array) {
-        checkArray(array, index);
-        return unsafe.getInt(array, Unsafe.ARRAY_INT_BASE_OFFSET + Unsafe.ARRAY_INT_INDEX_SCALE * index);
-    }
-
-    public long getArrayLong(long index, Object array) {
-        checkArray(array, index);
-        return unsafe.getLong(array, Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * index);
-    }
-
-    public double getArrayDouble(long index, Object array) {
-        checkArray(array, index);
-        return unsafe.getDouble(array, Unsafe.ARRAY_DOUBLE_BASE_OFFSET + Unsafe.ARRAY_DOUBLE_INDEX_SCALE * index);
-    }
-
-    public float getArrayFloat(long index, Object array) {
-        checkArray(array, index);
-        return unsafe.getFloat(array, Unsafe.ARRAY_FLOAT_BASE_OFFSET + Unsafe.ARRAY_FLOAT_INDEX_SCALE * index);
-    }
-
-    public Object getArrayObject(long index, Object array) {
-        checkArray(array, index);
-        return unsafe.getObject(array, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * index);
-    }
-
-    public void setArrayByte(byte value, long index, Object array) {
-        checkArray(array, index);
-        if (array instanceof boolean[]) {
-            checkArrayType(array, boolean.class);
-        } else {
-            checkArrayType(array, byte.class);
-        }
-        unsafe.putByte(array, Unsafe.ARRAY_BYTE_BASE_OFFSET + Unsafe.ARRAY_BYTE_INDEX_SCALE * index, value);
-    }
-
-    public void setArrayChar(char value, long index, Object array) {
-        checkArray(array, index);
-        checkArrayType(array, char.class);
-        unsafe.putChar(array, Unsafe.ARRAY_CHAR_BASE_OFFSET + Unsafe.ARRAY_CHAR_INDEX_SCALE * index, value);
-    }
-
-    public void setArrayShort(short value, long index, Object array) {
-        checkArray(array, index);
-        checkArrayType(array, short.class);
-        unsafe.putShort(array, Unsafe.ARRAY_SHORT_BASE_OFFSET + Unsafe.ARRAY_SHORT_INDEX_SCALE * index, value);
-    }
-
-    public void setArrayInt(int value, long index, Object array) {
-        checkArray(array, index);
-        checkArrayType(array, int.class);
-        unsafe.putInt(array, Unsafe.ARRAY_INT_BASE_OFFSET + Unsafe.ARRAY_INT_INDEX_SCALE * index, value);
-    }
-
-    public void setArrayLong(long value, long index, Object array) {
-        checkArray(array, index);
-        checkArrayType(array, long.class);
-        unsafe.putLong(array, Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * index, value);
-    }
-
-    public void setArrayFloat(float value, long index, Object array) {
-        checkArray(array, index);
-        checkArrayType(array, float.class);
-        unsafe.putFloat(array, Unsafe.ARRAY_FLOAT_BASE_OFFSET + Unsafe.ARRAY_FLOAT_INDEX_SCALE * index, value);
-    }
-
-    public void setArrayDouble(double value, long index, Object array) {
-        checkArray(array, index);
-        checkArrayType(array, double.class);
-        unsafe.putDouble(array, Unsafe.ARRAY_DOUBLE_BASE_OFFSET + Unsafe.ARRAY_DOUBLE_INDEX_SCALE * index, value);
-    }
-
-    public void setArrayObject(Object value, long index, Object array) {
-        checkArray(array, index);
-        checkArrayType(array, value != null ? value.getClass() : null);
-        unsafe.putObject(array, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * index, value);
-    }
-
-    private static void nullCheck(Object value) {
-        if (value == null) {
-            throw new NullPointerException();
-        }
-    }
-
-    private void checkArrayType(Object array, Class<?> arrayType) {
-        if (arrayType == null) {
-            return;
-        }
-        ResolvedJavaType type = getRuntime().getResolvedJavaType(array.getClass()).componentType();
-        if (!type.toJava().isAssignableFrom(arrayType)) {
-            throw new ArrayStoreException(arrayType.getName());
-        }
-    }
-
-    private void checkArray(Object array, long index) {
-        nullCheck(array);
-        ResolvedJavaType type = getRuntime().getResolvedJavaType(array.getClass());
-        if (!type.isArrayClass()) {
-            throw new ArrayStoreException(array.getClass().getName());
-        }
-        if (index < 0 || index >= arrayLength(array)) {
-            throw new ArrayIndexOutOfBoundsException((int) index);
-        }
-    }
-
-    private static int arrayLength(Object array) {
-        assert array != null;
-        return Array.getLength(array);
-    }
-
-    private static boolean isVolatile(ResolvedJavaField field) {
-        return Modifier.isVolatile(field.accessFlags());
-    }
-
-    private static long resolveOffset(ResolvedJavaField field) {
-        return ((HotSpotResolvedJavaField) field).offset();
-    }
-
-    private static Object resolveBase(Object base, ResolvedJavaField field) {
-        Object accessorBase = base;
-        if (accessorBase == null) {
-            accessorBase = field.holder().toJava();
-        }
-        return accessorBase;
-    }
-
-    private static Unsafe loadUnsafe() {
-        try {
-            return Unsafe.getUnsafe();
-        } catch (SecurityException e) {
-        }
-        try {
-            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
-            theUnsafeInstance.setAccessible(true);
-            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
-        } catch (Exception e) {
-            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
-        }
-    }
-
-    private static final VMAdapter instance = new VMAdapter();
-    public static VMAdapter getInstance() {
-        return instance;
-    }
-
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.java;
+
+import static com.oracle.graal.bytecode.Bytecodes.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.bytecode.*;
+
+/**
+ * Utility for producing a {@code javap}-like disassembly of bytecode.
+ */
+public class BytecodeDisassembler {
+
+    /**
+     * Specifies if the disassembly for a single instruction can span multiple lines.
+     */
+    private final boolean multiline;
+
+    public BytecodeDisassembler(boolean multiline) {
+        this.multiline = multiline;
+    }
+
+    public BytecodeDisassembler() {
+        this(true);
+    }
+
+    /**
+     * Disassembles the bytecode of a given method in a {@code javap}-like format.
+     *
+     * @return {@code null} if {@code method} has no bytecode (e.g., it is native or abstract)
+     */
+    public String disassemble(ResolvedJavaMethod method) {
+        if (method.code() == null) {
+            return null;
+        }
+        ConstantPool cp = method.getConstantPool();
+        BytecodeStream stream = new BytecodeStream(method.code());
+        StringBuilder buf = new StringBuilder();
+        int opcode = stream.currentBC();
+        while (opcode != Bytecodes.END) {
+            int bci = stream.currentBCI();
+            String mnemonic = Bytecodes.nameOf(opcode);
+            buf.append(String.format("%4d: %-14s", bci, mnemonic));
+            if (stream.nextBCI() > bci + 1) {
+                switch (opcode) {
+                    case BIPUSH         : buf.append(stream.readByte()); break;
+                    case SIPUSH         : buf.append(stream.readShort()); break;
+                    case NEW            :
+                    case CHECKCAST      :
+                    case INSTANCEOF     :
+                    case ANEWARRAY      : {
+                        int cpi = stream.readCPI();
+                        JavaType type = cp.lookupType(cpi, opcode);
+                        buf.append(String.format("#%-10d // %s", cpi, MetaUtil.toJavaName(type)));
+                        break;
+                    }
+                    case GETSTATIC      :
+                    case PUTSTATIC      :
+                    case GETFIELD       :
+                    case PUTFIELD       : {
+                        int cpi = stream.readCPI();
+                        JavaField field = cp.lookupField(cpi, opcode);
+                        String fieldDesc = field.holder().name().equals(method.holder().name()) ? MetaUtil.format("%n:%T", field) : MetaUtil.format("%H.%n:%T", field);
+                        buf.append(String.format("#%-10d // %s", cpi, fieldDesc));
+                        break;
+                    }
+                    case INVOKEVIRTUAL  :
+                    case INVOKESPECIAL  :
+                    case INVOKESTATIC   : {
+                        int cpi = stream.readCPI();
+                        JavaMethod callee = cp.lookupMethod(cpi, opcode);
+                        String calleeDesc = callee.holder().name().equals(method.holder().name()) ? MetaUtil.format("%n:(%P)%R", callee) : MetaUtil.format("%H.%n:(%P)%R", callee);
+                        buf.append(String.format("#%-10d // %s", cpi, calleeDesc));
+                        break;
+                    }
+                    case INVOKEINTERFACE: {
+                        int cpi = stream.readCPI();
+                        JavaMethod callee = cp.lookupMethod(cpi, opcode);
+                        String calleeDesc = callee.holder().name().equals(method.holder().name()) ? MetaUtil.format("%n:(%P)%R", callee) : MetaUtil.format("%H.%n:(%P)%R", callee);
+                        buf.append(String.format("#%-10s // %s", cpi + ", " + stream.readUByte(bci + 3), calleeDesc));
+                        break;
+                    }
+                    case LDC            :
+                    case LDC_W          :
+                    case LDC2_W         : {
+                        int cpi = stream.readCPI();
+                        Object constant = cp.lookupConstant(cpi);
+                        String desc = null;
+                        if (constant instanceof Constant) {
+                            Constant c = ((Constant) constant);
+                            switch (c.kind) {
+                                case Int :
+                                    desc = String.valueOf(c.asInt());
+                                    break;
+                                case Float:
+                                    desc = String.valueOf(c.asFloat());
+                                    break;
+                                case Object:
+                                    desc = Kind.Object.format(c.asObject());
+                                    break;
+                                case Double :
+                                    desc = String.valueOf(c.asDouble());
+                                    break;
+                                case Long :
+                                    desc = String.valueOf(c.asLong());
+                                    break;
+                                default:
+                                    desc = c.toString();
+                                    break;
+                            }
+                        } else {
+                            desc = constant.toString();
+                        }
+                        if (!multiline) {
+                            desc.replaceAll("\\n", "");
+                        }
+                        buf.append(String.format("#%-10d // %s", cpi, desc));
+                        break;
+                    }
+                    case RET            :
+                    case ILOAD          :
+                    case LLOAD          :
+                    case FLOAD          :
+                    case DLOAD          :
+                    case ALOAD          :
+                    case ISTORE         :
+                    case LSTORE         :
+                    case FSTORE         :
+                    case DSTORE         :
+                    case ASTORE         : {
+                        buf.append(String.format("%d", stream.readLocalIndex()));
+                        break;
+                    }
+                    case IFEQ           :
+                    case IFNE           :
+                    case IFLT           :
+                    case IFGE           :
+                    case IFGT           :
+                    case IFLE           :
+                    case IF_ICMPEQ      :
+                    case IF_ICMPNE      :
+                    case IF_ICMPLT      :
+                    case IF_ICMPGE      :
+                    case IF_ICMPGT      :
+                    case IF_ICMPLE      :
+                    case IF_ACMPEQ      :
+                    case IF_ACMPNE      :
+                    case GOTO           :
+                    case JSR            :
+                    case IFNULL         :
+                    case IFNONNULL      :
+                    case GOTO_W         :
+                    case JSR_W          : {
+                        buf.append(String.format("%d", stream.readBranchDest()));
+                        break;
+                    }
+                    case LOOKUPSWITCH   :
+                    case TABLESWITCH    : {
+                        BytecodeSwitch bswitch = opcode == LOOKUPSWITCH ? new BytecodeLookupSwitch(stream, bci) : new BytecodeTableSwitch(stream, bci);
+                        if (multiline) {
+                            buf.append("{ // " + bswitch.numberOfCases());
+                            for (int i = 0; i < bswitch.numberOfCases(); i++) {
+                                buf.append(String.format("%n           %7d: %d", bswitch.keyAt(i), bswitch.targetAt(i)));
+                            }
+                            buf.append(String.format("%n           default: %d", bswitch.defaultTarget()));
+                            buf.append(String.format("%n      }"));
+                        } else {
+                            buf.append("[" + bswitch.numberOfCases()).append("] {");
+                            for (int i = 0; i < bswitch.numberOfCases(); i++) {
+                                buf.append(String.format("%d: %d", bswitch.keyAt(i), bswitch.targetAt(i)));
+                                if (i != bswitch.numberOfCases() - 1) {
+                                    buf.append(", ");
+                                }
+                            }
+                            buf.append(String.format("} default: %d", bswitch.defaultTarget()));
+                        }
+                        break;
+                    }
+                    case NEWARRAY       : {
+                        int code = stream.readLocalIndex();
+                        // Checkstyle: stop
+                        switch (code) {
+                            case 4:  buf.append("boolean"); break;
+                            case 5:  buf.append("char"); break;
+                            case 6:  buf.append("float"); break;
+                            case 7:  buf.append("double"); break;
+                            case 8:  buf.append("byte"); break;
+                            case 9:  buf.append("short"); break;
+                            case 10: buf.append("int"); break;
+                            case 11: buf.append("long"); break;
+                        }
+                        // Checkstyle: resume
+
+                        break;
+                    }
+                    case MULTIANEWARRAY : {
+                        int cpi = stream.readCPI();
+                        JavaType type = cp.lookupType(cpi, opcode);
+                        buf.append(String.format("#%-10s // %s", cpi + ", " + stream.readUByte(bci + 3), MetaUtil.toJavaName(type)));
+                        break;
+                    }
+                }
+            }
+            buf.append(String.format("%n"));
+            stream.next();
+            opcode = stream.currentBC();
+        }
+        return buf.toString();
+    }
+}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Jul 05 16:54:45 2012 +0200
@@ -30,8 +30,8 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.JavaType.*;
-import com.oracle.graal.api.meta.JavaTypeProfile.*;
+import com.oracle.graal.api.meta.JavaType.Representation;
+import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
 import com.oracle.graal.bytecode.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
@@ -649,7 +649,7 @@
             ResolvedJavaType resolvedType = (ResolvedJavaType) type;
             ConstantNode hub = appendConstant(resolvedType.getEncoding(JavaType.Representation.ObjectHub));
             InstanceOfNode instanceOfNode = new InstanceOfNode(hub, (ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType));
-            frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode), currentGraph)));
+            frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode))));
         } else {
             BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode());
             DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved, graphId));
@@ -693,10 +693,10 @@
         // Checkstyle: resume
     }
 
-    private void genNewTypeArray(int typeCode) {
+    private void genNewPrimitiveArray(int typeCode) {
         Kind kind = arrayTypeCodeToKind(typeCode);
         ResolvedJavaType elementType = runtime.getResolvedJavaType(kind);
-        NewTypeArrayNode nta = currentGraph.add(new NewTypeArrayNode(frameState.ipop(), elementType));
+        NewPrimitiveArrayNode nta = currentGraph.add(new NewPrimitiveArrayNode(frameState.ipop(), elementType));
         frameState.apush(append(nta));
     }
 
@@ -965,7 +965,11 @@
             return;
         }
 
-        MethodCallTargetNode callTarget = currentGraph.add(new MethodCallTargetNode(invokeKind, targetMethod, args, targetMethod.signature().returnType(method.holder())));
+        JavaType returnType = targetMethod.signature().returnType(method.holder());
+        if (graphBuilderConfig.eagerResolvingForSnippets()) {
+            returnType = returnType.resolve(targetMethod.holder());
+        }
+        MethodCallTargetNode callTarget = currentGraph.add(new MethodCallTargetNode(invokeKind, targetMethod, args, returnType));
         // be conservative if information was not recorded (could result in endless recompiles otherwise)
         if (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == ExceptionSeen.FALSE) {
             ValueNode result = appendWithBCI(currentGraph.add(new InvokeNode(callTarget, bci(), graphId)));
@@ -1705,7 +1709,7 @@
             case INVOKESTATIC   : cpi = stream.readCPI(); genInvokeStatic(lookupMethod(cpi, opcode)); break;
             case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(lookupMethod(cpi, opcode)); break;
             case NEW            : genNewInstance(stream.readCPI()); break;
-            case NEWARRAY       : genNewTypeArray(stream.readLocalIndex()); break;
+            case NEWARRAY       : genNewPrimitiveArray(stream.readLocalIndex()); break;
             case ANEWARRAY      : genNewObjectArray(stream.readCPI()); break;
             case ARRAYLENGTH    : genArrayLength(); break;
             case ATHROW         : genThrow(); break;
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy01.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy01.java	Thu Jul 05 16:54:45 2012 +0200
@@ -31,6 +31,10 @@
 
     public static Object[] src = new Object[]{null, null};
     public static Object[] dest = new Object[]{null, null};
+    static {
+        // Ensure System is resolved
+        System.arraycopy(src, 0, src, 0, src.length);
+    }
 
     public static int test(int srcPos, int destPos, int length) {
         System.arraycopy(src, srcPos, dest, destPos, length);
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy02.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy02.java	Thu Jul 05 16:54:45 2012 +0200
@@ -32,6 +32,10 @@
     public static int[] src = new int[]{0, 1, 2, 3, 4, 5};
     public static int[] dest0 = new int[]{5, 4, 3, 2, 1, 0};
     public static int[] dest = new int[]{5, 4, 3, 2, 1, 0};
+    static {
+        // Ensure System is resolved
+        System.arraycopy(src, 0, src, 0, src.length);
+    }
 
     @Before
     public void setUp() {
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy03.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy03.java	Thu Jul 05 16:54:45 2012 +0200
@@ -32,6 +32,10 @@
     public static byte[] src = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
     public static byte[] dest0 = new byte[]{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
     public static byte[] dest = new byte[]{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
+    static {
+        // Ensure System is resolved
+        System.arraycopy(src, 0, src, 0, src.length);
+    }
 
     @Before
     public void setUp() {
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy04.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy04.java	Thu Jul 05 16:54:45 2012 +0200
@@ -31,6 +31,10 @@
 
     public static byte[] array = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
     public static byte[] array0 = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+    static {
+        // Ensure System is resolved
+        System.arraycopy(array, 0, array, 0, array.length);
+    }
 
     @Before
     public void setUp() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy05.java	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.jtt.optimize;
+
+import org.junit.*;
+
+/*
+ * Tests calls to the array copy method.
+ */
+public class ArrayCopy05 {
+
+    public static char[] array = new char[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+    public static char[] array0 = new char[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+    static {
+        // Ensure System is resolved
+        System.arraycopy(array, 0, array, 0, array.length);
+    }
+
+    @Before
+    public void setUp() {
+        System.currentTimeMillis();
+        for (int i = 0; i < array.length; i++) {
+            array[i] = array0[i];
+        }
+    }
+
+    public static char[] test(int srcPos, int destPos, int length) {
+        System.arraycopy(array, srcPos, array, destPos, length);
+        return array;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        Assert.assertArrayEquals(new char[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 0));
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run1() throws Throwable {
+        test(0, 0, -1);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run2() throws Throwable {
+        test(-1, 0, 0);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run3() throws Throwable {
+        test(0, -1, 0);
+    }
+
+    @Test
+    public void run4() throws Throwable {
+        Assert.assertArrayEquals(new char[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 2));
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run5() throws Throwable {
+        test(0, 1, 11);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run6() throws Throwable {
+        test(1, 0, 11);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run7() throws Throwable {
+        test(1, 1, -1);
+    }
+
+    @Test
+    public void run8() throws Throwable {
+        Assert.assertArrayEquals(new char[] {0, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 1, 2));
+    }
+
+    @Test
+    public void run9() throws Throwable {
+        Assert.assertArrayEquals(new char[] {1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(1, 0, 2));
+    }
+
+    @Test
+    public void run10() throws Throwable {
+        Assert.assertArrayEquals(new char[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(1, 1, 2));
+    }
+
+    @Test
+    public void run11() throws Throwable {
+        Assert.assertArrayEquals(new char[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 6));
+    }
+
+    @Test
+    public void run12() throws Throwable {
+        Assert.assertArrayEquals(new char[] {0, 0, 1, 2, 3, 4, 6, 7, 8, 9, 10}, test(0, 1, 5));
+    }
+
+    @Test
+    public void run13() throws Throwable {
+        Assert.assertArrayEquals(new char[] {1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10}, test(1, 0, 5));
+    }
+
+    @Test
+    public void run14() throws Throwable {
+        Assert.assertArrayEquals(new char[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(1, 1, 5));
+    }
+
+    @Test
+    public void run15() throws Throwable {
+        Assert.assertArrayEquals(new char[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 11));
+    }
+
+    @Test
+    public void run16() throws Throwable {
+        Assert.assertArrayEquals(new char[] {0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, test(0, 1, 10));
+    }
+
+    @Test
+    public void run17() throws Throwable {
+        Assert.assertArrayEquals(new char[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10}, test(1, 0, 10));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy06.java	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.jtt.optimize;
+
+import org.junit.*;
+
+/*
+ * Tests calls to the array copy method.
+ */
+public class ArrayCopy06 {
+
+    public static short[] array = new short[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+    public static short[] array0 = new short[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+    static {
+        // Ensure System is resolved
+        System.arraycopy(array, 0, array, 0, array.length);
+    }
+
+    @Before
+    public void setUp() {
+        System.currentTimeMillis();
+        for (int i = 0; i < array.length; i++) {
+            array[i] = array0[i];
+        }
+    }
+
+    public static short[] test(int srcPos, int destPos, int length) {
+        System.arraycopy(array, srcPos, array, destPos, length);
+        return array;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        Assert.assertArrayEquals(new short[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 0));
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run1() throws Throwable {
+        test(0, 0, -1);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run2() throws Throwable {
+        test(-1, 0, 0);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run3() throws Throwable {
+        test(0, -1, 0);
+    }
+
+    @Test
+    public void run4() throws Throwable {
+        Assert.assertArrayEquals(new short[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 2));
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run5() throws Throwable {
+        test(0, 1, 11);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run6() throws Throwable {
+        test(1, 0, 11);
+    }
+
+    @Test(expected = java.lang.IndexOutOfBoundsException.class)
+    public void run7() throws Throwable {
+        test(1, 1, -1);
+    }
+
+    @Test
+    public void run8() throws Throwable {
+        Assert.assertArrayEquals(new short[] {0, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 1, 2));
+    }
+
+    @Test
+    public void run9() throws Throwable {
+        Assert.assertArrayEquals(new short[] {1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(1, 0, 2));
+    }
+
+    @Test
+    public void run10() throws Throwable {
+        Assert.assertArrayEquals(new short[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(1, 1, 2));
+    }
+
+    @Test
+    public void run11() throws Throwable {
+        Assert.assertArrayEquals(new short[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 6));
+    }
+
+    @Test
+    public void run12() throws Throwable {
+        Assert.assertArrayEquals(new short[] {0, 0, 1, 2, 3, 4, 6, 7, 8, 9, 10}, test(0, 1, 5));
+    }
+
+    @Test
+    public void run13() throws Throwable {
+        Assert.assertArrayEquals(new short[] {1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10}, test(1, 0, 5));
+    }
+
+    @Test
+    public void run14() throws Throwable {
+        Assert.assertArrayEquals(new short[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(1, 1, 5));
+    }
+
+    @Test
+    public void run15() throws Throwable {
+        Assert.assertArrayEquals(new short[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 11));
+    }
+
+    @Test
+    public void run16() throws Throwable {
+        Assert.assertArrayEquals(new short[] {0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, test(0, 1, 10));
+    }
+
+    @Test
+    public void run17() throws Throwable {
+        Assert.assertArrayEquals(new short[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10}, test(1, 0, 10));
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -146,7 +146,7 @@
                                 return;
                             }
                             if (trueValue.isConstant() && falseValue.isConstant()) {
-                                MaterializeNode materialize = MaterializeNode.create(compare(), graph(), trueValue, falseValue);
+                                MaterializeNode materialize = MaterializeNode.create(compare(), trueValue, falseValue);
                                 ((StructuredGraph) graph()).replaceFloating(singlePhi, materialize);
                                 removeEmptyIf(tool);
                                 return;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -27,18 +27,59 @@
 
 public final class MaterializeNode extends ConditionalNode {
 
+    private static CompareNode createCompareNode(Condition condition, ValueNode x, ValueNode y) {
+        assert x.kind() == y.kind();
+        assert condition.isCanonical() : "condition is not canonical: " + condition;
+
+        assert !x.kind().isFloatOrDouble();
+        CompareNode comparison;
+        if (condition == Condition.EQ) {
+            if (x.kind().isObject()) {
+                comparison = new ObjectEqualsNode(x, y);
+            } else {
+                assert x.kind().stackKind().isInt() || x.kind().isLong();
+                comparison = new IntegerEqualsNode(x, y);
+            }
+        } else if (condition == Condition.LT) {
+            assert x.kind().stackKind().isInt() || x.kind().isLong();
+            comparison = new IntegerLessThanNode(x, y);
+        } else {
+            assert condition == Condition.BT;
+            assert x.kind().stackKind().isInt() || x.kind().isLong();
+            comparison = new IntegerBelowThanNode(x, y);
+        }
+
+        return x.graph().unique(comparison);
+    }
+
+    private MaterializeNode(Condition condition, ValueNode x, ValueNode y) {
+        this(createCompareNode(condition, x, y), ConstantNode.forInt(1, x.graph()), ConstantNode.forInt(0, x.graph()));
+    }
+
     private MaterializeNode(BooleanNode condition, ValueNode trueValue, ValueNode falseValue) {
         super(condition, trueValue, falseValue);
     }
 
-    public static MaterializeNode create(BooleanNode condition, Graph graph, ValueNode trueValue, ValueNode falseValue) {
+    public static MaterializeNode create(BooleanNode condition, ValueNode trueValue, ValueNode falseValue) {
+        Graph graph = condition.graph();
         MaterializeNode result = new MaterializeNode(condition, trueValue, falseValue);
         return graph.unique(result);
 
     }
 
-    public static MaterializeNode create(BooleanNode condition, Graph graph) {
-        return create(condition, graph, ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph));
+    public static MaterializeNode create(BooleanNode condition) {
+        return create(condition, ConstantNode.forInt(1, condition.graph()), ConstantNode.forInt(0, condition.graph()));
     }
 
+    @NodeIntrinsic
+    @SuppressWarnings("unused")
+    public static boolean materialize(@ConstantNodeParameter Condition condition, int x, int y) {
+        throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler");
+    }
+
+    @NodeIntrinsic
+    @SuppressWarnings("unused")
+    public static boolean materialize(@ConstantNodeParameter Condition condition, long x, long y) {
+        throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler");
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -158,17 +158,17 @@
 
     public final ObjectStamp objectStamp() {
         assert verifyStamp(ObjectStamp.class);
-        return (ObjectStamp) stamp;
+        return (ObjectStamp) stamp();
     }
 
     public final IntegerStamp integerStamp() {
         assert verifyStamp(IntegerStamp.class);
-        return (IntegerStamp) stamp;
+        return (IntegerStamp) stamp();
     }
 
     public final FloatStamp floatStamp() {
         assert verifyStamp(FloatStamp.class);
-        return (FloatStamp) stamp;
+        return (FloatStamp) stamp();
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes.calc;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -80,7 +79,7 @@
     }
 
 
-    private ValueNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, CodeCacheProvider runtime, Condition cond) {
+    private ValueNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, MetaAccessProvider runtime, Condition cond) {
         Constant trueConstant = conditionalNode.trueValue().asConstant();
         Constant falseConstant = conditionalNode.falseValue().asConstant();
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -58,8 +58,8 @@
             lessComp = graph.unique(new IntegerLessThanNode(x(), y()));
         }
 
-        MaterializeNode equalValue = MaterializeNode.create(equalComp, graph, ConstantNode.forInt(0, graph), ConstantNode.forInt(1, graph));
-        MaterializeNode value =  MaterializeNode.create(lessComp, graph, ConstantNode.forInt(-1, graph), equalValue);
+        MaterializeNode equalValue = MaterializeNode.create(equalComp, ConstantNode.forInt(0, graph), ConstantNode.forInt(1, graph));
+        MaterializeNode value =  MaterializeNode.create(lessComp, ConstantNode.forInt(-1, graph), equalValue);
 
         graph.replaceFloating(this, value);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxingMethodPool.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxingMethodPool.java	Thu Jul 05 16:54:45 2012 +0200
@@ -24,18 +24,17 @@
 
 import java.util.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 
 public class BoxingMethodPool {
 
     private final Set<JavaMethod> specialMethods = new HashSet<>();
-    private final CodeCacheProvider runtime;
+    private final MetaAccessProvider runtime;
     private final ResolvedJavaMethod[] boxingMethods = new ResolvedJavaMethod[Kind.values().length];
     private final ResolvedJavaMethod[] unboxingMethods = new ResolvedJavaMethod[Kind.values().length];
     private final ResolvedJavaField[] boxFields = new ResolvedJavaField[Kind.values().length];
 
-    public BoxingMethodPool(CodeCacheProvider runtime) {
+    public BoxingMethodPool(MetaAccessProvider runtime) {
         this.runtime = runtime;
         initialize();
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -60,7 +59,7 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        CodeCacheProvider runtime = tool.runtime();
+        MetaAccessProvider runtime = tool.runtime();
         if (runtime != null && object() != null && object().isConstant() && object().kind() == Kind.Object) {
             if (this.location() == LocationNode.FINAL_LOCATION && location().getClass() == LocationNode.class) {
                 Object value = object().asConstant().asObject();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadHubNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadHubNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaType.*;
 import com.oracle.graal.nodes.*;
@@ -49,7 +48,7 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        CodeCacheProvider runtime = tool.runtime();
+        MetaAccessProvider runtime = tool.runtime();
         if (runtime != null) {
             ObjectStamp stamp = object.objectStamp();
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -43,7 +42,7 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        CodeCacheProvider runtime = tool.runtime();
+        MetaAccessProvider runtime = tool.runtime();
         if (runtime != null && object() != null && object().isConstant() && object().kind() == Kind.Object) {
             if (location() == LocationNode.FINAL_LOCATION && location().getClass() == LocationNode.class) {
                 Object value = object().asConstant().asObject();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes.java;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -51,7 +50,7 @@
             assert length != null;
             return length;
         }
-        CodeCacheProvider runtime = tool.runtime();
+        MetaAccessProvider runtime = tool.runtime();
         if (runtime != null && array().isConstant() && !array().isNullConstant()) {
             Constant constantValue = array().asConstant();
             if (constantValue != null && constantValue.isNonNull()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes.java;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -55,7 +54,7 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        CodeCacheProvider runtime = tool.runtime();
+        MetaAccessProvider runtime = tool.runtime();
         if (runtime != null) {
             Constant constant = null;
             if (isStatic()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -24,7 +24,6 @@
 
 import java.lang.reflect.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -61,7 +60,7 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        CodeCacheProvider runtime = tool.runtime();
+        MetaAccessProvider runtime = tool.runtime();
         if (runtime != null && index().isConstant() && array().isConstant() && !array().isNullConstant()) {
             Constant arrayConst = array().asConstant();
             if (tool.isImmutable(arrayConst)) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -36,7 +36,7 @@
 /**
  * The {@code NewArrayNode} class is the base of all instructions that allocate arrays.
  */
-public abstract class NewArrayNode extends FixedWithNextNode implements EscapeAnalyzable, TypeFeedbackProvider {
+public abstract class NewArrayNode extends FixedWithNextNode implements Lowerable, EscapeAnalyzable, TypeFeedbackProvider {
 
     @Input private ValueNode length;
 
@@ -86,6 +86,11 @@
         return ESCAPE;
     }
 
+    @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
+    }
+
     private static final EscapeOp ESCAPE = new EscapeOp() {
 
         @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewPrimitiveArrayNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,51 @@
+/*
+ * 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.graal.nodes.java;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * The {@code NewPrimitiveArrayNode} class definition.
+ */
+public final class NewPrimitiveArrayNode extends NewArrayNode implements LIRLowerable {
+
+    private final ResolvedJavaType elementType;
+
+    public NewPrimitiveArrayNode(ValueNode length, ResolvedJavaType elementType) {
+        super(StampFactory.exactNonNull(elementType.arrayOf()), length);
+        this.elementType = elementType;
+    }
+
+    @Override
+    public ResolvedJavaType elementType() {
+        return elementType;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool gen) {
+        gen.visitNewPrimitiveArray(this);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewTypeArrayNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +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.graal.nodes.java;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-/**
- * The {@code NewTypeArrayNode} class definition.
- */
-public final class NewTypeArrayNode extends NewArrayNode implements LIRLowerable {
-
-    private final ResolvedJavaType elementType;
-
-    public NewTypeArrayNode(ValueNode length, ResolvedJavaType elementType) {
-        super(StampFactory.exactNonNull(elementType.arrayOf()), length);
-        this.elementType = elementType;
-    }
-
-    @Override
-    public ResolvedJavaType elementType() {
-        return elementType;
-    }
-
-    @Override
-    public void generate(LIRGeneratorTool gen) {
-        gen.visitNewTypeArray(this);
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/CanonicalizerTool.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/CanonicalizerTool.java	Thu Jul 05 16:54:45 2012 +0200
@@ -29,7 +29,7 @@
 public interface CanonicalizerTool {
     TargetDescription target();
     Assumptions assumptions();
-    CodeCacheProvider runtime();
+    MetaAccessProvider runtime();
 
     /**
      * Determines if a given constant is an object/array whose current
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Thu Jul 05 16:54:45 2012 +0200
@@ -112,7 +112,7 @@
     public abstract void visitMonitorEnter(MonitorEnterNode i);
     public abstract void visitMonitorExit(MonitorExitNode i);
     public abstract void visitNewInstance(NewInstanceNode i);
-    public abstract void visitNewTypeArray(NewTypeArrayNode i);
+    public abstract void visitNewPrimitiveArray(NewPrimitiveArrayNode i);
     public abstract void visitNewObjectArray(NewObjectArrayNode i);
     public abstract void visitNewMultiArray(NewMultiArrayNode i);
     public abstract void visitExceptionObject(ExceptionObjectNode i);
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java	Thu Jul 05 16:54:45 2012 +0200
@@ -134,6 +134,12 @@
         stream.println("  ]]></bytecodes>");
     }
 
+    protected void printBytecodes(String disassembly) {
+        beginBytecodes();
+        stream.println(disassembly);
+        endBytecodes();
+    }
+
     protected void endMethod() {
         stream.println(" </method>");
     }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Thu Jul 05 16:54:45 2012 +0200
@@ -24,6 +24,7 @@
 
 import java.io.*;
 import java.util.*;
+import java.util.concurrent.atomic.*;
 
 import com.oracle.graal.alloc.util.*;
 import com.oracle.graal.api.code.*;
@@ -46,6 +47,7 @@
 public class CFGPrinterObserver implements DebugDumpHandler {
 
     private CFGPrinter cfgPrinter;
+    private File cfgFile;
     private ResolvedJavaMethod curMethod;
     private List<String> curDecorators = Collections.emptyList();
 
@@ -63,7 +65,7 @@
      * in the current debug scope and opens a new compilation scope if this pair
      * does not match the current method and decorator pair.
      */
-    private void checkMethodScope() {
+    private boolean checkMethodScope() {
         ResolvedJavaMethod method = null;
         ArrayList<String> decorators = new ArrayList<>();
         for (Object o : Debug.context()) {
@@ -83,14 +85,22 @@
             }
         }
 
+        if (method == null) {
+            return false;
+        }
+
         if (method != curMethod || !curDecorators.equals(decorators)) {
             cfgPrinter.printCompilation(method);
-            TTY.println("CFGPrinter: Dumping method %s", method);
+            TTY.println("CFGPrinter: Dumping method %s to %s", method, cfgFile);
             curMethod = method;
             curDecorators = decorators;
         }
+        return true;
     }
 
+    private static final long timestamp = System.currentTimeMillis();
+    private static final AtomicInteger uniqueId = new AtomicInteger();
+
     public void dumpSandboxed(Object object, String message) {
         GraalCompiler compiler = Debug.contextLookup(GraalCompiler.class);
         if (compiler == null) {
@@ -98,17 +108,19 @@
         }
 
         if (cfgPrinter == null) {
-            File file = new File("compilations-" + System.currentTimeMillis() + ".cfg");
+            cfgFile = new File("compilations-" + timestamp + "_" + uniqueId.incrementAndGet() + ".cfg");
             try {
-                OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
+                OutputStream out = new BufferedOutputStream(new FileOutputStream(cfgFile));
                 cfgPrinter = new CFGPrinter(out);
             } catch (FileNotFoundException e) {
-                throw new GraalInternalError("Could not open " + file.getAbsolutePath());
+                throw new GraalInternalError("Could not open " + cfgFile.getAbsolutePath());
             }
-            TTY.println("CFGPrinter: Output to file %s", file);
+            TTY.println("CFGPrinter: Output to file %s", cfgFile);
         }
 
-        checkMethodScope();
+        if (!checkMethodScope()) {
+            return;
+        }
 
         cfgPrinter.target = compiler.target;
         if (object instanceof LIR) {
@@ -126,7 +138,9 @@
         if (object instanceof BciBlockMapping) {
             BciBlockMapping blockMap = (BciBlockMapping) object;
             cfgPrinter.printCFG(message, blockMap);
-            cfgPrinter.printBytecodes(runtime.disassemble(blockMap.method));
+            if (blockMap.method.code() != null) {
+                cfgPrinter.printBytecodes(new BytecodeDisassembler(false).disassemble(blockMap.method));
+            }
 
         } else if (object instanceof LIR) {
             cfgPrinter.printCFG(message, cfgPrinter.lir.codeEmittingOrder());
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Thu Jul 05 16:54:45 2012 +0200
@@ -27,12 +27,12 @@
 import java.util.Map.Entry;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.bytecode.*;
 import com.oracle.graal.compiler.schedule.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.graph.NodeClass.Position;
+import com.oracle.graal.java.*;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
 
@@ -57,23 +57,8 @@
         printProperty("name", name);
         endProperties();
         beginMethod(name, shortName, bci);
-        if (method != null) {
-            beginBytecodes();
-            BytecodeStream bytecodes = new BytecodeStream(method.code());
-            while (bytecodes.currentBC() != Bytecodes.END) {
-                int startBCI = bytecodes.currentBCI();
-                String mnemonic = Bytecodes.nameOf(bytecodes.currentBC());
-                int[] extra = null;
-                if (bytecodes.nextBCI() > startBCI + 1) {
-                    extra = new int[bytecodes.nextBCI() - (startBCI + 1)];
-                    for (int i = 0; i < extra.length; i++) {
-                        extra[i] = bytecodes.readUByte(startBCI + 1 + i);
-                    }
-                }
-                printBytecode(startBCI, mnemonic, extra);
-                bytecodes.next();
-            }
-            endBytecodes();
+        if (method != null && method.code() != null) {
+            printBytecodes(new BytecodeDisassembler(false).disassemble(method));
         }
         endMethod();
     }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java	Thu Jul 05 16:54:45 2012 +0200
@@ -58,11 +58,26 @@
         boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller);
 
         /**
-         * The default inlining policy which inlines everything except for
-         * constructors of {@link Throwable} classes.
+         * The default inlining policy which inlines everything except for methods
+         * in any of the following categories.
+         * <ul>
+         * <li>{@linkplain Fold foldable} methods</li>
+         * <li>{@linkplain NodeIntrinsic node intrinsics}</li>
+         * <li>native methods</li>
+         * <li>constructors of {@link Throwable} classes</li>
+         * </ul>
          */
         InliningPolicy Default = new InliningPolicy() {
             public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) {
+                if (Modifier.isNative(method.accessFlags())) {
+                    return false;
+                }
+                if (method.getAnnotation(Fold.class) != null) {
+                    return false;
+                }
+                if (method.getAnnotation(NodeIntrinsic.class) != null) {
+                    return false;
+                }
                 if (Throwable.class.isAssignableFrom(method.holder().toJava())) {
                     if (method.name().equals("<init>")) {
                         return false;
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Thu Jul 05 16:54:45 2012 +0200
@@ -37,7 +37,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.snippets.Snippet.InliningPolicy;
 
 /**
@@ -45,7 +44,7 @@
  */
 public class SnippetInstaller {
 
-    private final GraalCodeCacheProvider runtime;
+    private final MetaAccessProvider runtime;
     private final TargetDescription target;
     private final BoxingMethodPool pool;
 
@@ -57,7 +56,7 @@
      */
     private final Map<ResolvedJavaMethod, StructuredGraph> graphCache;
 
-    public SnippetInstaller(GraalCodeCacheProvider runtime, TargetDescription target) {
+    public SnippetInstaller(MetaAccessProvider runtime, TargetDescription target) {
         this.runtime = runtime;
         this.target = target;
         this.pool = new BoxingMethodPool(runtime);
@@ -137,6 +136,8 @@
     public StructuredGraph makeGraph(final ResolvedJavaMethod method, final InliningPolicy policy) {
         StructuredGraph graph = parseGraph(method, policy);
 
+        new SnippetIntrinsificationPhase(runtime, pool, SnippetTemplate.hasConstantParameter(method)).apply(graph);
+
         Debug.dump(graph, "%s: Final", method.name());
 
         return graph;
@@ -165,7 +166,7 @@
 
                 new SnippetVerificationPhase().apply(graph);
 
-                new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
+                new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph);
 
                 for (Invoke invoke : graph.getInvokes()) {
                     MethodCallTargetNode callTarget = invoke.callTarget();
@@ -181,7 +182,7 @@
                     }
                 }
 
-                new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
+                new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph);
 
                 new WordTypeRewriterPhase(target.wordKind, runtime.getResolvedJavaType(target.wordKind)).apply(graph);
 
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java	Thu Jul 05 16:54:45 2012 +0200
@@ -25,7 +25,6 @@
 import java.lang.reflect.*;
 import java.util.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
@@ -39,18 +38,41 @@
 
 public class SnippetIntrinsificationPhase extends Phase {
 
-    private final CodeCacheProvider runtime;
+    private final MetaAccessProvider runtime;
     private final BoxingMethodPool pool;
+    private final boolean intrinsificationOrFoldingCanBeDeferred;
 
-    public SnippetIntrinsificationPhase(CodeCacheProvider runtime, BoxingMethodPool pool) {
+    /**
+     * @param intrinsificationOrFoldingCanBeDeferred if true, then {@link NonConstantParameterError}s are not fatal
+     */
+    public SnippetIntrinsificationPhase(MetaAccessProvider runtime, BoxingMethodPool pool, boolean intrinsificationOrFoldingCanBeDeferred) {
         this.runtime = runtime;
         this.pool = pool;
+        this.intrinsificationOrFoldingCanBeDeferred = intrinsificationOrFoldingCanBeDeferred;
     }
 
     @Override
     protected void run(StructuredGraph graph) {
         for (Invoke i : graph.getInvokes()) {
-            tryIntrinsify(i);
+            try {
+                tryIntrinsify(i);
+            } catch (NonConstantParameterError t) {
+                if (!intrinsificationOrFoldingCanBeDeferred) {
+                    throw t;
+                }
+            }
+        }
+    }
+
+    /**
+     * Exception raised when an argument to a {@linkplain Fold foldable} or
+     * {@link NodeIntrinsic} method is not a constant.
+     */
+    @SuppressWarnings("serial")
+    public static class NonConstantParameterError extends Error {
+
+        public NonConstantParameterError(String message) {
+            super(message);
         }
     }
 
@@ -119,7 +141,9 @@
             }
             ValueNode argument = tryBoxingElimination(parameterIndex, target, arguments.get(i));
             if (folding || MetaUtil.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) {
-                assert argument instanceof ConstantNode : "parameter " + parameterIndex + " must be a compile time constant for calling " + invoke.callTarget().targetMethod() + " at " + sourceLocation(invoke.node()) + ": " + argument;
+                if (!(argument instanceof ConstantNode)) {
+                    throw new NonConstantParameterError("parameter " + parameterIndex + " must be a compile time constant for calling " + invoke.callTarget().targetMethod() + " at " + sourceLocation(invoke.node()) + ": " + argument);
+                }
                 ConstantNode constantNode = (ConstantNode) argument;
                 Constant constant = constantNode.asConstant();
                 Object o = constant.boxedValue();
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Thu Jul 05 16:54:45 2012 +0200
@@ -35,6 +35,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
@@ -175,6 +176,18 @@
     }
 
     /**
+     * Determines if any parameter of a given method is annotated with {@link ConstantParameter}.
+     */
+    public static boolean hasConstantParameter(ResolvedJavaMethod method) {
+        for (ConstantParameter p : MetaUtil.getParameterAnnotations(ConstantParameter.class, method)) {
+            if (p != null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * Creates a snippet template.
      */
     public SnippetTemplate(CodeCacheProvider runtime, SnippetTemplate.Key key) {
@@ -182,7 +195,7 @@
         assert Modifier.isStatic(method.accessFlags()) : "snippet method must be static: " + method;
         Signature signature = method.signature();
 
-        // Copy snippet graph, replacing @Constant parameters with given arguments
+        // Copy snippet graph, replacing constant parameters with given arguments
         StructuredGraph snippetGraph = (StructuredGraph) method.compilerStorage().get(Graph.class);
         StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method());
         IdentityHashMap<Node, Node> replacements = new IdentityHashMap<>();
@@ -201,7 +214,8 @@
                 replacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(Constant.forBoxed(kind, arg), runtime, snippetCopy));
             } else {
                 Parameter p = MetaUtil.getParameterAnnotation(Parameter.class, i, method);
-                assert p != null : method + ": parameter " + i + " must be annotated with either @Constant or @Parameter";
+                assert p != null : method + ": parameter " + i + " must be annotated with either @" + ConstantParameter.class.getSimpleName() +
+                                " or @" + Parameter.class.getSimpleName();
                 String name = p.value();
                 if (p.multiple()) {
                     Object multiple = key.get(name);
@@ -219,6 +233,9 @@
 
         Debug.dump(snippetCopy, "Before specialization");
         if (!replacements.isEmpty()) {
+            // Do deferred intrinsification of node intrinsics
+            new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime), false).apply(snippetCopy);
+
             new CanonicalizerPhase(null, runtime, null, 0, null).apply(snippetCopy);
         }
 
@@ -386,6 +403,7 @@
                     replacements.put((LocalNode) parameter, (ValueNode) argument);
                 } else {
                     Kind kind = ((LocalNode) parameter).kind();
+                    assert argument != null || kind.isObject() : this + " cannot accept null for non-object parameter named " + name;
                     Constant constant = Constant.forBoxed(kind, argument);
                     replacements.put((LocalNode) parameter, ConstantNode.forConstant(constant, runtime, replaceeGraph));
                 }
@@ -478,10 +496,10 @@
             sep = ", ";
             if (value instanceof LocalNode) {
                 LocalNode local = (LocalNode) value;
-                buf.append(local.kind().name()).append(' ').append(name);
+                buf.append(local.kind().javaName).append(' ').append(name);
             } else {
                 LocalNode[] locals = (LocalNode[]) value;
-                String kind = locals.length == 0 ? "?" : locals[0].kind().name();
+                String kind = locals.length == 0 ? "?" : locals[0].kind().javaName;
                 buf.append(kind).append('[').append(locals.length).append("] ").append(name);
             }
         }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java	Thu Jul 05 16:54:45 2012 +0200
@@ -31,6 +31,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.snippets.Word.*;
@@ -87,6 +88,11 @@
                             argc++;
                         }
                     }
+                } else if (usage instanceof ObjectEqualsNode) {
+                    ObjectEqualsNode compare = (ObjectEqualsNode) usage;
+                    if (compare.x() == node || compare.y() == node) {
+                        verify(isWord(compare.x()) == isWord(compare.y()), node, compare.usages().first(), "cannot mixed word and now-word type in use of '==' or '!='");
+                    }
                 } else if (usage instanceof ArrayLengthNode) {
                     verify(!isWord(node) || ((ArrayLengthNode) usage).array() != node, node, usage, "cannot get array length from word value");
                 } else if (usage instanceof PhiNode) {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java	Thu Jul 05 16:54:45 2012 +0200
@@ -68,6 +68,17 @@
             }
         }
 
+        // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are words
+        for (ObjectEqualsNode objectEqualsNode : graph.getNodes().filter(ObjectEqualsNode.class).snapshot()) {
+            ValueNode x = objectEqualsNode.x();
+            ValueNode y = objectEqualsNode.y();
+            if (x.kind() == wordKind || y.kind() == wordKind) {
+                assert x.kind() == wordKind;
+                assert y.kind() == wordKind;
+                graph.replaceFloating(objectEqualsNode, graph.unique(new IntegerEqualsNode(x, y)));
+            }
+        }
+
         for (MethodCallTargetNode callTargetNode : graph.getNodes(MethodCallTargetNode.class).snapshot()) {
             ResolvedJavaMethod targetMethod = callTargetNode.targetMethod();
             Operation operation = targetMethod.getAnnotation(Word.Operation.class);
@@ -188,7 +199,7 @@
         ValueNode a = mirror ? right : left;
         ValueNode b = mirror ? left : right;
 
-        MaterializeNode materialize = MaterializeNode.create(graph.unique(new IntegerBelowThanNode(a, b)), graph);
+        MaterializeNode materialize = MaterializeNode.create(graph.unique(new IntegerBelowThanNode(a, b)));
 
         ValueNode op;
         if (condition.canonicalNegate()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/NewArrayTest.java	Thu Jul 05 16:54:45 2012 +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.graal.compiler.tests;
+
+import org.junit.*;
+
+/**
+ * Tests the implementation of {@code [A]NEWARRAY}.
+ */
+public class NewArrayTest extends GraalCompilerTest {
+
+    @Override
+    protected void assertEquals(Object expected, Object actual) {
+        Assert.assertTrue(expected != null);
+        Assert.assertTrue(actual != null);
+        super.assertEquals(expected.getClass(), actual.getClass());
+        if (expected instanceof int[]) {
+            Assert.assertArrayEquals((int[]) expected, (int[]) actual);
+        } else if (expected instanceof byte[]) {
+            Assert.assertArrayEquals((byte[]) expected, (byte[]) actual);
+        } else if (expected instanceof char[]) {
+            Assert.assertArrayEquals((char[]) expected, (char[]) actual);
+        } else if (expected instanceof short[]) {
+            Assert.assertArrayEquals((short[]) expected, (short[]) actual);
+        } else if (expected instanceof float[]) {
+            Assert.assertArrayEquals((float[]) expected, (float[]) actual, 0.0f);
+        } else if (expected instanceof long[]) {
+            Assert.assertArrayEquals((long[]) expected, (long[]) actual);
+        } else if (expected instanceof double[]) {
+            Assert.assertArrayEquals((double[]) expected, (double[]) actual, 0.0d);
+        } else if (expected instanceof Object[]) {
+            Assert.assertArrayEquals((Object[]) expected, (Object[]) actual);
+        } else {
+            Assert.fail("non-array value encountered: " + expected);
+        }
+    }
+
+    @Test
+    public void test1() {
+        for (String type : new String[] {"Byte", "Char", "Short", "Int", "Float", "Long", "Double", "String"}) {
+            test("new" + type + "Array7");
+            test("new" + type + "ArrayMinus7");
+            test("new" + type + "Array", 7);
+            test("new" + type + "Array", -7);
+            test("new" + type + "Array", Integer.MAX_VALUE);
+            test("new" + type + "Array", Integer.MIN_VALUE);
+        }
+    }
+
+    public static Object newCharArray7() {
+        return new char[7];
+    }
+
+    public static Object newCharArrayMinus7() {
+        return new char[-7];
+    }
+
+    public static Object newCharArray(int length) {
+        return new char[length];
+    }
+
+    public static Object newShortArray7() {
+        return new short[7];
+    }
+
+    public static Object newShortArrayMinus7() {
+        return new short[-7];
+    }
+
+    public static Object newShortArray(int length) {
+        return new short[length];
+    }
+
+    public static Object newFloatArray7() {
+        return new float[7];
+    }
+
+    public static Object newFloatArrayMinus7() {
+        return new float[-7];
+    }
+
+    public static Object newFloatArray(int length) {
+        return new float[length];
+    }
+
+    public static Object newLongArray7() {
+        return new long[7];
+    }
+
+    public static Object newLongArrayMinus7() {
+        return new long[-7];
+    }
+
+    public static Object newLongArray(int length) {
+        return new long[length];
+    }
+
+    public static Object newDoubleArray7() {
+        return new double[7];
+    }
+
+    public static Object newDoubleArrayMinus7() {
+        return new double[-7];
+    }
+
+    public static Object newDoubleArray(int length) {
+        return new double[length];
+    }
+
+    public static Object newIntArray7() {
+        return new int[7];
+    }
+
+    public static Object newIntArrayMinus7() {
+        return new int[-7];
+    }
+
+    public static Object newIntArray(int length) {
+        return new int[length];
+    }
+
+    public static Object newByteArray7() {
+        return new byte[7];
+    }
+
+    public static Object newByteArrayMinus7() {
+        return new byte[-7];
+    }
+
+    public static Object newByteArray(int length) {
+        return new byte[length];
+    }
+
+    public static Object newStringArray7() {
+        return new String[7];
+    }
+
+    public static Object newStringArrayMinus7() {
+        return new String[-7];
+    }
+
+    public static Object newStringArray(int length) {
+        return new String[length];
+    }
+}
--- a/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/UnsignedMath.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/UnsignedMath.java	Thu Jul 05 16:54:45 2012 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.max.criutils;
 
+//JaCoCo Exclude
+
 /**
  * Utilities for unsigned comparisons.
  * All methods have correct, but slow, standard Java implementations so that
--- a/mx/commands.py	Thu Jul 05 16:54:00 2012 +0200
+++ b/mx/commands.py	Thu Jul 05 16:54:45 2012 +0200
@@ -587,7 +587,9 @@
         # Exclude all compiler tests and snippets
         excludes = ['com.oracle.graal.compiler.tests.*']
         for p in mx.projects():
-            _find_classes_with_annotations(excludes, p, None, ['@Snippet', '@ClassSubstitution'], includeInnerClasses=True)
+            excludes += _find_classes_with_annotations(p, None, ['@Snippet', '@ClassSubstitution'], includeInnerClasses=True)
+            excludes += p.find_classes_with_matching_source_line(None, lambda line: 'JaCoCo Exclude' in line, includeInnerClasses=True)
+            
         agentOptions = {
                         'append' : 'true' if _jacoco == 'append' else 'false',
                         'bootclasspath' : 'true',
@@ -598,47 +600,15 @@
     exe = join(jdk, 'bin', mx.exe_suffix('java'))
     return mx.run([exe, '-' + vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout)
 
-def _find_classes_with_annotations(classes, p, pkgRoot, annotations, includeInnerClasses=False):
+def _find_classes_with_annotations(p, pkgRoot, annotations, includeInnerClasses=False):
     """
     Scan the sources of project 'p' for Java source files containing a line starting with 'annotation'
-    (ignoring preceding whitespace) and add the fully qualified class name
-    to 'classes' for each Java source file matched.
+    (ignoring preceding whitespace) and return the fully qualified class name for each Java
+    source file matched in a list.
     """
-    for a in annotations:
-        assert a.startswith('@')
-    pkgDecl = re.compile(r"^package\s+([a-zA-Z_][\w\.]*)\s*;$")
-    for srcDir in p.source_dirs():
-        outputDir = p.output_dir()
-        for root, _, files in os.walk(srcDir):
-            for name in files:
-                if name.endswith('.java') and name != 'package-info.java':
-                    annotationFound = False
-                    with open(join(root, name)) as f:
-                        pkg = None
-                        for line in f:
-                            if line.startswith("package "):
-                                match = pkgDecl.match(line)
-                                if match:
-                                    pkg = match.group(1)
-                            else:
-                                stripped = line.strip()
-                                for a in annotations:
-                                    if stripped == a or stripped.startswith(a + '('):
-                                        annotationFound = True
-                                        break
-                                if annotationFound:
-                                    break
-                    if annotationFound:
-                        basename = name[:-len('.java')]
-                        assert pkg is not None
-                        if pkgRoot is None or pkg.startswith(pkgRoot):
-                            pkgOutputDir = join(outputDir, pkg.replace('.', os.path.sep))
-                            for e in os.listdir(pkgOutputDir):
-                                if includeInnerClasses:
-                                    if e.endswith('.class') and (e.startswith(basename) or e.startswith(basename + '$')):
-                                        classes.append(pkg + '.' + e[:-len('.class')])
-                                elif e == basename + '.class':
-                                    classes.append(pkg + '.' + basename)
+    
+    matches = lambda line : len([a for a in annotations if line == a or line.startswith(a + '(')]) != 0
+    return p.find_classes_with_matching_source_line(pkgRoot, matches, includeInnerClasses)
 
 def _run_tests(args, harnessName, harness):
     pos = [a for a in args if a[0] != '-' and a[0] != '@' ]
@@ -653,8 +623,7 @@
 
     for p in mx.projects():
         if getattr(p, 'testHarness', None) == harnessName:
-            classes = []
-            _find_classes_with_annotations(classes, p, None, ['@Test'])
+            classes = _find_classes_with_annotations(p, None, ['@Test'])
 
             if len(pos) != 0:
                 classes = [c for c in classes if containsAny(c, pos)]
@@ -739,7 +708,7 @@
 
     parser = ArgumentParser(prog='mx gate');
     parser.add_argument('-j', '--omit-java-clean', action='store_false', dest='cleanJava', help='omit cleaning Java native code')
-    parser.add_argument('-n', '--omit-native-build', action='store_false', dest='buildNative', help='omit cleaning and building native code')
+    parser.add_argument('-n', '--omit-native-clean', action='store_false', dest='cleanNative', help='omit cleaning and building native code')
     parser.add_argument('-g', '--only-build-graalvm', action='store_false', dest='buildNonGraal', help='only build the Graal VM')
     parser.add_argument('--jacocout', help='specify the output directory for jacoco report')
 
@@ -755,7 +724,7 @@
 
         t = Task('Clean')
         cleanArgs = []
-        if not args.buildNative:
+        if not args.cleanNative:
             cleanArgs.append('--no-native')
         if not args.cleanJava:
             cleanArgs.append('--no-java')
@@ -768,10 +737,9 @@
         for vmbuild in ['fastdebug', 'product']:
             _vmbuild = vmbuild
 
-            if args.buildNative:
-                t = Task('BuildHotSpotGraal:' + vmbuild)
-                buildvms(['--vms', 'graal', '--builds', vmbuild])
-                tasks.append(t.stop())
+            t = Task('BuildHotSpotGraal:' + vmbuild)
+            buildvms(['--vms', 'graal', '--builds', vmbuild])
+            tasks.append(t.stop())
 
             t = Task('BootstrapWithSystemAssertions:' + vmbuild)
             vm(['-esa', '-version'])
@@ -823,7 +791,7 @@
         tasks.append(t.stop())
 
         # Prevent Graal modifications from breaking the standard builds
-        if args.buildNative and args.buildNonGraal:
+        if args.buildNonGraal:
             t = Task('BuildHotSpotVarieties')
             buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product'])
             tasks.append(t.stop())
--- a/mxtool/mx.py	Thu Jul 05 16:54:00 2012 +0200
+++ b/mxtool/mx.py	Thu Jul 05 16:54:45 2012 +0200
@@ -261,6 +261,46 @@
         if not self.native:
             cp.append(self.output_dir())
 
+    def find_classes_with_matching_source_line(self, pkgRoot, function, includeInnerClasses=False):
+        """
+        Scan the sources of this project for Java source files containing a line for which
+        'function' returns true. The fully qualified class name of each existing class
+        corresponding to a matched source file is returned in a list.
+        """
+        classes = []
+        pkgDecl = re.compile(r"^package\s+([a-zA-Z_][\w\.]*)\s*;$")
+        for srcDir in self.source_dirs():
+            outputDir = self.output_dir()
+            for root, _, files in os.walk(srcDir):
+                for name in files:
+                    if name.endswith('.java') and name != 'package-info.java':
+                        matchFound = False
+                        with open(join(root, name)) as f:
+                            pkg = None
+                            for line in f:
+                                if line.startswith("package "):
+                                    match = pkgDecl.match(line)
+                                    if match:
+                                        pkg = match.group(1)
+                                if function(line.strip()):
+                                    matchFound = True
+                                if pkg and matchFound:
+                                    break
+                                        
+                        if matchFound:
+                            basename = name[:-len('.java')]
+                            assert pkg is not None
+                            if pkgRoot is None or pkg.startswith(pkgRoot):
+                                pkgOutputDir = join(outputDir, pkg.replace('.', os.path.sep))
+                                for e in os.listdir(pkgOutputDir):
+                                    if includeInnerClasses:
+                                        if e.endswith('.class') and (e.startswith(basename) or e.startswith(basename + '$')):
+                                            classes.append(pkg + '.' + e[:-len('.class')])
+                                    elif e == basename + '.class':
+                                        classes.append(pkg + '.' + basename)
+        return classes
+    
+
 class Library(Dependency):
     def __init__(self, suite, name, path, mustExist, urls):
         Dependency.__init__(self, suite, name)
--- a/src/cpu/x86/vm/jniTypes_x86.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/cpu/x86/vm/jniTypes_x86.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -127,6 +127,12 @@
   static inline oop     get_obj   (intptr_t *from) { return *(oop *)    from; }
   static inline jfloat  get_float (intptr_t *from) { return *(jfloat *) from; }
   static inline jdouble get_double(intptr_t *from) { return *(jdouble *)(from + _JNI_SLOT_OFFSET); }
+
+  static inline jint    get_int   (intptr_t *from, int& pos) { return get_int(from + pos++); }
+  static inline jlong   get_long  (intptr_t *from, int& pos) { return get_long(from + pos); pos += 2; }
+  static inline oop     get_obj   (intptr_t *from, int& pos) { return get_obj(from + pos++); }
+  static inline jfloat  get_float (intptr_t *from, int& pos) { return get_float(from + pos++); }
+  static inline jdouble get_double(intptr_t *from, int& pos) { return get_double(from + pos); pos += 2; }
 #undef _JNI_SLOT_OFFSET
 };
 
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Thu Jul 05 16:54:45 2012 +0200
@@ -1340,7 +1340,7 @@
                                    methodOopDesc::invocation_counter_offset() +
                                    InvocationCounter::counter_offset());
   const Address access_flags(rbx, methodOopDesc::access_flags_offset());
-
+  
   // get parameter size (always needed)
   __ load_unsigned_short(rcx, size_of_parameters);
 
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -49,7 +49,7 @@
     public BytecodeNode(InputBytecode bytecode, InputGraph graph, String bciValue) {
 
         super(Children.LEAF);
-        this.setDisplayName(bytecode.getBci() + " " + bytecode.getName());
+        String displayName = bytecode.getBci() + " " + bytecode.getName() + " " + bytecode.getOperands();
 
         bciValue = bytecode.getBci() + " " + bciValue;
         bciValue = bciValue.trim();
@@ -62,8 +62,14 @@
             for (InputNode n : nodeList) {
                 nodes.add(n);
             }
-            this.setDisplayName(this.getDisplayName() + " (" + nodes.size() + " nodes)");
+            displayName += " (" + nodes.size() + " nodes)";
         }
+        
+        if (bytecode.getComment() != null) {
+            displayName += " // " + bytecode.getComment();
+        }
+        
+        this.setDisplayName(displayName);
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java	Thu Jul 05 16:54:45 2012 +0200
@@ -31,11 +31,15 @@
 
     private int bci;
     private String name;
+    private String operands;
+    private String comment;
     private InputMethod inlined;
 
-    public InputBytecode(int bci, String name) {
+    public InputBytecode(int bci, String name, String operands, String comment) {
         this.bci = bci;
         this.name = name;
+        this.operands = operands;
+        this.comment = comment;
     }
 
     public InputMethod getInlined() {
@@ -53,4 +57,12 @@
     public String getName() {
         return name;
     }
+
+    public String getOperands() {
+        return operands;
+    }
+
+    public String getComment() {
+        return comment;
+    }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java	Thu Jul 05 16:54:45 2012 +0200
@@ -26,6 +26,8 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  *
@@ -109,31 +111,38 @@
     }
 
     public void setBytecodes(String text) {
-
+        Pattern instruction = Pattern.compile("\\s*(\\d+)\\s*:?\\s*(\\w+)\\s*(.*)(?://(.*))?");
         String[] strings = text.split("\n");
-        int oldNumber = -1;
+        int oldBci = -1;
         for (String s : strings) {
-
-            if (s.length() > 0 && Character.isDigit(s.charAt(0))) {
-                s = s.trim();
-                int spaceIndex = s.indexOf(' ');
-                String numberString = s.substring(0, spaceIndex);
-                String tmpName = s.substring(spaceIndex + 1, s.length());
+            s = s.trim();
+            if (s.length() != 0) {
+                final Matcher matcher = instruction.matcher(s);
+                if (matcher.matches()) {
+                    String bciString = matcher.group(1);
+                    String opcode = matcher.group(2);
+                    String operands = matcher.group(3).trim();
+                    String comment = matcher.group(4);
+                    if (comment != null) {
+                        comment = comment.trim();
+                    }
 
-                int number = -1;
-                number = Integer.parseInt(numberString);
+                    int bci = Integer.parseInt(bciString);
 
-                // assert correct order of bytecodes
-                assert number > oldNumber;
+                    // assert correct order of bytecodes
+                    assert bci > oldBci;
+
+                    InputBytecode bc = new InputBytecode(bci, opcode, operands, comment);
+                    bytecodes.add(bc);
 
-                InputBytecode bc = new InputBytecode(number, tmpName);
-                bytecodes.add(bc);
-
-                for (InputMethod m : inlined) {
-                    if (m.getBci() == number) {
-                        bc.setInlined(m);
-                        break;
+                    for (InputMethod m : inlined) {
+                        if (m.getBci() == bci) {
+                            bc.setInlined(m);
+                            break;
+                        }
                     }
+                } else {
+                    System.out.println("no match: " + s);
                 }
             }
         }
--- a/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Thu Jul 05 16:54:45 2012 +0200
@@ -40,5 +40,5 @@
 
 # Disable assertions for RequestProcessor to prevent annoying messages in case
 # of multiple SceneAnimator update tasks in the default RequestProcessor.
-run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx2g
+run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx4g
 debug.args.extra = -J-server -J-da:org.openide.util.RequestProcessor
--- a/src/share/vm/classfile/javaClasses.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/classfile/javaClasses.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -255,6 +255,7 @@
  public:
   // Instance creation
   static oop create();
+  static int java_thread_offset_in_bytes() { return _eetop_offset; }
   // Returns the JavaThread associated with the thread obj
   static JavaThread* thread(oop java_thread);
   // Set JavaThread for instance
--- a/src/share/vm/classfile/vmSymbols.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -352,6 +352,10 @@
   template(callbackInternal_name,                 "callbackInternal")                                                                 \
   template(callback_signature,                    "(Ljava/lang/Object;)Ljava/lang/Object;")                                           \
   template(MethodInvalidatedException,            "com/oracle/graal/api/meta/InstalledCode$MethodInvalidatedException")               \
+  /* graal.api.interpreter */                                                                                                         \
+  template(com_oracle_graal_api_interpreter_Interpreter,             "com/oracle/graal/api/interpreter/Interpreter")                  \
+  template(interpreter_execute_name,              "execute")                                                                          \
+  template(interpreter_execute_signature,         "(Lcom/oracle/graal/api/meta/ResolvedJavaMethod;[Ljava/lang/Object;)Ljava/lang/Object;") \
                                                                                                                                       \
                                                                                                   \
   /* common method and field names */                                                             \
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -21,6 +21,9 @@
  * questions.
  */
 
+#ifndef SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP
+#define SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP
+
 /*
  * This class handles the conversion from a InstalledCode to a CodeBlob or an nmethod.
  */
@@ -112,3 +115,4 @@
 
 };
 
+#endif // SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP
--- a/src/share/vm/graal/graalCompiler.cpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Thu Jul 05 16:54:45 2012 +0200
@@ -273,7 +273,7 @@
   HotSpotResolvedJavaType::set_accessFlags(obj, klass->access_flags().as_int());
   HotSpotResolvedJavaType::set_isInterface(obj, klass->is_interface());
   HotSpotResolvedJavaType::set_superCheckOffset(obj, klass->super_check_offset());
-  HotSpotResolvedJavaType::set_prototypeHeader(obj, (jlong) klass->prototype_header());
+  HotSpotResolvedJavaType::set_initialMarkWord(obj, (jlong) klass->prototype_header());
   HotSpotResolvedJavaType::set_isInstanceClass(obj, klass->oop_is_instance());
 
   if (klass->oop_is_javaArray()) {
--- a/src/share/vm/graal/graalCompiler.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/graal/graalCompiler.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -21,6 +21,9 @@
  * questions.
  */
 
+#ifndef SHARE_VM_GRAAL_GRAAL_COMPILER_HPP
+#define SHARE_VM_GRAAL_GRAAL_COMPILER_HPP
+
 #include "compiler/abstractCompiler.hpp"
 
 #define LEAF_GRAPH_ARRAY_SIZE (8192)
@@ -110,5 +113,4 @@
 #define TRACE_graal_4 if (!(TraceGraal >= 4 && (tty->print("         TraceGraal-4: "), true))) ; else tty->print_cr
 #define TRACE_graal_5 if (!(TraceGraal >= 5 && (tty->print("            TraceGraal-5: "), true))) ; else tty->print_cr
 
-
-
+#endif // SHARE_VM_GRAAL_GRAAL_COMPILER_HPP
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu Jul 05 16:54:45 2012 +0200
@@ -790,6 +790,7 @@
   set_int(env, config, "vmPageSize", os::vm_page_size());
   set_int(env, config, "stackShadowPages", StackShadowPages);
   set_int(env, config, "hubOffset", oopDesc::klass_offset_in_bytes());
+  set_int(env, config, "markOffset", oopDesc::mark_offset_in_bytes());
   set_int(env, config, "superCheckOffsetOffset", in_bytes(Klass::super_check_offset_offset()));
   set_int(env, config, "secondarySuperCacheOffset", in_bytes(Klass::secondary_super_cache_offset()));
   set_int(env, config, "secondarySupersOffset", in_bytes(Klass::secondary_supers_offset()));
@@ -802,7 +803,7 @@
   set_int(env, config, "instanceHeaderPrototypeOffset", in_bytes(Klass::prototype_header_offset()));
   set_int(env, config, "threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset()));
   set_int(env, config, "threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset()));
-  set_int(env, config, "threadMultiNewArrayStorage", in_bytes(JavaThread::graal_multinewarray_storage_offset()));
+  set_int(env, config, "threadMultiNewArrayStorageOffset", in_bytes(JavaThread::graal_multinewarray_storage_offset()));
   set_int(env, config, "classMirrorOffset", in_bytes(Klass::java_mirror_offset()));
   
   set_int(env, config, "methodDataOopDataOffset", in_bytes(methodDataOopDesc::data_offset()));
@@ -874,12 +875,6 @@
       break;
     }
 
-  jintArray arrayOffsets = env->NewIntArray(basicTypeCount);
-  for (int i=0; i<basicTypeCount; i++) {
-    jint offset = arrayOopDesc::base_offset_in_bytes(basicTypes[i]);
-    env->SetIntArrayRegion(arrayOffsets, i, 1, &offset);
-  }
-  set_int_array(env, config, "arrayOffsets", arrayOffsets);
   set_int(env, config, "arrayClassElementOffset", in_bytes(objArrayKlass::element_klass_offset()));
   return config;
 }
@@ -934,25 +929,6 @@
   return JNIHandles::make_local(result());
 }
 
-// public String disassembleJava(HotSpotResolvedJavaMethod method);
-JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_disassembleJava(JNIEnv *env, jobject, jobject hotspot_method) {
-  TRACE_graal_3("CompilerToVM::disassembleJava");
-
-  // Important: The bytecode printing functions are all NOT PRODUCT code, so this method returns an empty string for a product VM build.
-
-  VM_ENTRY_MARK;
-  ResourceMark rm;
-  HandleMark hm;
-
-  methodHandle method = getMethodFromHotSpotMethod(hotspot_method);
-  // Note: cannot use resource-allocated stringStream because print_code_on has its own ResourceMark.
-  bufferedStream(st);
-  method->print_codes_on(&st);
-
-  Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL);
-  return JNIHandles::make_local(result());
-}
-
 // public StackTraceElement JavaMethod_toStackTraceElement(HotSpotResolvedJavaMethod method, int bci);
 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_JavaMethod_1toStackTraceElement(JNIEnv *env, jobject, jobject hotspot_method, int bci) {
   TRACE_graal_3("CompilerToVM::JavaMethod_toStackTraceElement");
@@ -966,48 +942,6 @@
   return JNIHandles::make_local(element);
 }
 
-class JavaArgumentPusher : public SignatureIterator {
- protected:
-  JavaCallArguments*  _jca;
-  arrayOop _args;
-  int _index;
-
-  oop next_arg(BasicType expectedType) {
-    assert(_index < _args->length(), "out of bounds");
-    oop arg = ((oop*) _args->base(T_OBJECT))[_index++];
-    assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch");
-    return arg;
-  }
-
- public:
-  JavaArgumentPusher(Symbol* signature, JavaCallArguments*  jca, arrayOop args, bool is_static) : SignatureIterator(signature) {
-    this->_return_type = T_ILLEGAL;
-    _jca = jca;
-    _index = 0;
-    _args = args;
-    if (!is_static) {
-      _jca->push_oop(next_arg(T_OBJECT));
-    }
-    iterate();
-    assert(_index == args->length(), "arg count mismatch with signature");
-  }
-
-  inline void do_bool()   { if (!is_return_type()) _jca->push_int(next_arg(T_BOOLEAN)->bool_field(java_lang_boxing_object::value_offset_in_bytes(T_BOOLEAN))); }
-  inline void do_char()   { if (!is_return_type()) _jca->push_int(next_arg(T_CHAR)->char_field(java_lang_boxing_object::value_offset_in_bytes(T_CHAR))); }
-  inline void do_short()  { if (!is_return_type()) _jca->push_int(next_arg(T_SHORT)->short_field(java_lang_boxing_object::value_offset_in_bytes(T_SHORT))); }
-  inline void do_byte()   { if (!is_return_type()) _jca->push_int(next_arg(T_BYTE)->byte_field(java_lang_boxing_object::value_offset_in_bytes(T_BYTE))); }
-  inline void do_int()    { if (!is_return_type()) _jca->push_int(next_arg(T_INT)->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT))); }
-
-  inline void do_long()   { if (!is_return_type()) _jca->push_long(next_arg(T_LONG)->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG))); }
-  inline void do_float()  { if (!is_return_type()) _jca->push_float(next_arg(T_FLOAT)->float_field(java_lang_boxing_object::value_offset_in_bytes(T_FLOAT))); }
-  inline void do_double() { if (!is_return_type()) _jca->push_double(next_arg(T_DOUBLE)->double_field(java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE))); }
-
-  inline void do_object() { _jca->push_oop(next_arg(T_OBJECT)); }
-  inline void do_object(int begin, int end) { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); }
-  inline void do_array(int begin, int end)  { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); }
-  inline void do_void()                     { }
-};
-
 // public Object executeCompiledMethodVarargs(HotSpotCompiledMethod method, Object... args);
 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_executeCompiledMethodVarargs(JNIEnv *env, jobject, jobject method, jobject args) {
   TRACE_graal_3("CompilerToVM::executeCompiledMethod");
@@ -1021,7 +955,7 @@
   Symbol* signature = mh->signature();
   JavaCallArguments jca;
 
-  JavaArgumentPusher jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static());
+  JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static());
   JavaValue result(jap.get_ret_type());
 
   nmethod* nm = (nmethod*) HotSpotCompiledMethod::nmethod(method);
@@ -1182,7 +1116,6 @@
   {CC"getConfiguration",                  CC"()"CONFIG,                                         FN_PTR(getConfiguration)},
   {CC"installMethod",                     CC"("TARGET_METHOD"Z"HS_CODE_INFO")"HS_COMP_METHOD,   FN_PTR(installMethod)},
   {CC"disassembleNative",                 CC"([BJ)"STRING,                                      FN_PTR(disassembleNative)},
-  {CC"disassembleJava",                   CC"("RESOLVED_METHOD")"STRING,                        FN_PTR(disassembleJava)},
   {CC"JavaMethod_toStackTraceElement",      CC"("RESOLVED_METHOD"I)"STACK_TRACE_ELEMENT,          FN_PTR(JavaMethod_1toStackTraceElement)},
   {CC"executeCompiledMethod",             CC"("HS_COMP_METHOD OBJECT OBJECT OBJECT")"OBJECT,    FN_PTR(executeCompiledMethod)},
   {CC"executeCompiledMethodVarargs",      CC"("HS_COMP_METHOD "["OBJECT")"OBJECT,               FN_PTR(executeCompiledMethodVarargs)},
--- a/src/share/vm/graal/graalCompilerToVM.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -21,13 +21,59 @@
  * questions.
  */
 
+#ifndef SHARE_VM_GRAAL_GRAAL_COMPILER_TO_VM_HPP
+#define SHARE_VM_GRAAL_GRAAL_COMPILER_TO_VM_HPP
+
 #include "prims/jni.h"
 
 extern JNINativeMethod CompilerToVM_methods[];
 int CompilerToVM_methods_count();
 
+methodOop getMethodFromHotSpotMethod(jobject hotspotMethod);
 methodOop getMethodFromHotSpotMethod(oop hotspotMethod);
 
+class JavaArgumentUnboxer : public SignatureIterator {
+ protected:
+  JavaCallArguments*  _jca;
+  arrayOop _args;
+  int _index;
+
+  oop next_arg(BasicType expectedType) {
+    assert(_index < _args->length(), "out of bounds");
+    oop arg = ((oop*) _args->base(T_OBJECT))[_index++];
+    assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch");
+    return arg;
+  }
+
+ public:
+  JavaArgumentUnboxer(Symbol* signature, JavaCallArguments*  jca, arrayOop args, bool is_static) : SignatureIterator(signature) {
+    this->_return_type = T_ILLEGAL;
+    _jca = jca;
+    _index = 0;
+    _args = args;
+    if (!is_static) {
+      _jca->push_oop(next_arg(T_OBJECT));
+    }
+    iterate();
+    assert(_index == args->length(), "arg count mismatch with signature");
+  }
+
+  inline void do_bool()   { if (!is_return_type()) _jca->push_int(next_arg(T_BOOLEAN)->bool_field(java_lang_boxing_object::value_offset_in_bytes(T_BOOLEAN))); }
+  inline void do_char()   { if (!is_return_type()) _jca->push_int(next_arg(T_CHAR)->char_field(java_lang_boxing_object::value_offset_in_bytes(T_CHAR))); }
+  inline void do_short()  { if (!is_return_type()) _jca->push_int(next_arg(T_SHORT)->short_field(java_lang_boxing_object::value_offset_in_bytes(T_SHORT))); }
+  inline void do_byte()   { if (!is_return_type()) _jca->push_int(next_arg(T_BYTE)->byte_field(java_lang_boxing_object::value_offset_in_bytes(T_BYTE))); }
+  inline void do_int()    { if (!is_return_type()) _jca->push_int(next_arg(T_INT)->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT))); }
+
+  inline void do_long()   { if (!is_return_type()) _jca->push_long(next_arg(T_LONG)->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG))); }
+  inline void do_float()  { if (!is_return_type()) _jca->push_float(next_arg(T_FLOAT)->float_field(java_lang_boxing_object::value_offset_in_bytes(T_FLOAT))); }
+  inline void do_double() { if (!is_return_type()) _jca->push_double(next_arg(T_DOUBLE)->double_field(java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE))); }
+
+  inline void do_object() { _jca->push_oop(next_arg(T_OBJECT)); }
+  inline void do_object(int begin, int end) { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); }
+  inline void do_array(int begin, int end)  { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); }
+  inline void do_void()                     { }
+};
+
 // nothing here - no need to define the jni method implementations in a header file
 
-
+#endif // SHARE_VM_GRAAL_GRAAL_COMPILER_TO_VM_HPP
--- a/src/share/vm/graal/graalEnv.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/graal/graalEnv.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -139,4 +139,3 @@
 };
 
 #endif // SHARE_VM_GRAAL_GRAALENV_HPP
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalInterpreterToVM.cpp	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#include "precompiled.hpp"
+#include "prims/jni.h"
+#include "graal/graalInterpreterToVM.hpp"
+#include "graal/graalCompiler.hpp"
+#include "graal/graalCompilerToVM.hpp"
+
+#ifdef HIGH_LEVEL_INTERPRETER
+
+// public Object invoke(HotSpotResolvedJavaMethod method, boolean highLevel, Object... args);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_HotSpotRuntimeInterpreterInterface_invoke(JNIEnv *env, jobject, jobject method, jobject args) {
+  TRACE_graal_3("InterpreterToVM::invoke");
+
+  VM_ENTRY_MARK;
+  HandleMark hm;
+  
+  assert(method != NULL, "just checking");
+  assert(thread->is_Java_thread(), "must be");
+  methodHandle mh = getMethodFromHotSpotMethod(method);
+    
+  JavaCallArguments jca;
+  JavaArgumentUnboxer jap(mh->signature(), &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static());
+  
+#ifndef PRODUCT
+  if (PrintHighLevelInterpreterVMTransitions) {
+    ResourceMark rm;
+    tty->print_cr("High level interpreter -> VM (%s)", mh->name_and_sig_as_C_string());
+  }
+#endif
+
+  JavaValue result(jap.get_ret_type());
+  thread->set_high_level_interpreter_in_vm(true);
+  JavaCalls::call(&result, mh, &jca, THREAD);
+  thread->set_high_level_interpreter_in_vm(false);
+
+#ifndef PRODUCT
+  if (PrintHighLevelInterpreterVMTransitions) {
+    ResourceMark rm;
+    tty->print_cr("VM (%s) -> high level interpreter", mh->name_and_sig_as_C_string());
+  }
+#endif
+
+  if (thread->has_pending_exception()) {
+    return NULL;
+  }
+
+  if (jap.get_ret_type() == T_VOID) {
+    return NULL;
+  } else if (jap.get_ret_type() == T_OBJECT || jap.get_ret_type() == T_ARRAY) {
+    return JNIHandles::make_local((oop) result.get_jobject());
+  } else {
+    oop o = java_lang_boxing_object::create(jap.get_ret_type(), (jvalue *) result.get_value_addr(), CHECK_NULL);
+    return JNIHandles::make_local(o);
+  }
+}
+
+#define CC (char*)  /*cast a literal from (const char*)*/
+#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(Java_com_oracle_graal_hotspot_HotSpotRuntimeInterpreterInterface_##f))
+
+#define RESOLVED_METHOD "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;"
+#define OBJECT          "Ljava/lang/Object;"
+
+JNINativeMethod InterpreterToVM_methods[] = {
+  {CC"invoke",                     CC"("RESOLVED_METHOD "["OBJECT")"OBJECT,     FN_PTR(invoke)}
+};
+
+int InterpreterToVM_methods_count() {
+  return sizeof(InterpreterToVM_methods) / sizeof(JNINativeMethod);
+}
+
+#endif // HIGH_LEVEL_INTERPRETER
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalInterpreterToVM.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+#ifdef HIGH_LEVEL_INTERPRETER
+#ifndef SHARE_VM_GRAAL_GRAAL_INTERPRETER_TO_VM_HPP
+#define SHARE_VM_GRAAL_GRAAL_INTERPRETER_TO_VM_HPP
+
+#include "prims/jni.h"
+
+extern JNINativeMethod InterpreterToVM_methods[];
+int InterpreterToVM_methods_count();
+
+// nothing here - no need to define the jni method implementations in a header file
+
+#endif // SHARE_VM_GRAAL_GRAAL_INTERPRETER_TO_VM_HPP
+#endif // HIGH_LEVEL_INTERPRETER
--- a/src/share/vm/graal/graalJavaAccess.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -21,6 +21,9 @@
  * questions.
  */
 
+#ifndef SHARE_VM_GRAAL_GRAAL_JAVA_ACCESS_HPP
+#define SHARE_VM_GRAAL_GRAAL_JAVA_ACCESS_HPP
+
 void graal_compute_offsets();
 
 #include "classfile/systemDictionary.hpp"
@@ -49,7 +52,7 @@
     oop_field(HotSpotResolvedJavaType, javaMirror, "Ljava/lang/Class;")                     \
     oop_field(HotSpotResolvedJavaType, simpleName, "Ljava/lang/String;")                    \
     int_field(HotSpotResolvedJavaType, accessFlags)                                         \
-    long_field(HotSpotResolvedJavaType, prototypeHeader)                                    \
+    long_field(HotSpotResolvedJavaType, initialMarkWord)                                    \
     boolean_field(HotSpotResolvedJavaType, hasFinalizer)                                    \
     boolean_field(HotSpotResolvedJavaType, hasFinalizableSubclass)                          \
     int_field(HotSpotResolvedJavaType, superCheckOffset)                                    \
@@ -294,3 +297,5 @@
 #undef STATIC_OOP_FIELD
 
 void compute_offset(int &dest_offset, klassOop klass_oop, const char* name, const char* signature, bool static_field);
+
+#endif // SHARE_VM_GRAAL_GRAAL_JAVA_ACCESS_HPP
--- a/src/share/vm/graal/graalRuntime.cpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Thu Jul 05 16:54:45 2012 +0200
@@ -27,5 +27,6 @@
 
 // JVM_InitializeGraalRuntime
 JVM_ENTRY(jobject, JVM_InitializeGraalRuntime(JNIEnv *env, jclass graalclass))
+  VMToCompiler::compilerInstance();
   return VMToCompiler::compilerPermObject();
 JVM_END
\ No newline at end of file
--- a/src/share/vm/graal/graalRuntime.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/graal/graalRuntime.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -21,6 +21,9 @@
  * questions.
  */
 
+#ifndef SHARE_VM_GRAAL_GRAAL_RUNTIME_HPP
+#define SHARE_VM_GRAAL_GRAAL_RUNTIME_HPP
+
 class GraalRuntime : public AllStatic {
 
 private:
@@ -29,4 +32,6 @@
 public:
   static jobject instance() { return _runtimeObject; }
 
-};
\ No newline at end of file
+};
+
+#endif // SHARE_VM_GRAAL_GRAAL_RUNTIME_HPP
--- a/src/share/vm/graal/graalVMToCompiler.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -21,6 +21,9 @@
  * questions.
  */
 
+#ifndef SHARE_VM_GRAAL_GRAAL_VM_TO_COMPILER_HPP
+#define SHARE_VM_GRAAL_GRAAL_VM_TO_COMPILER_HPP
+
 #include "memory/allocation.hpp"
 #include "oops/oop.hpp"
 #include "runtime/handles.hpp"
@@ -122,3 +125,4 @@
   }
 }
 
+#endif // SHARE_VM_GRAAL_GRAAL_VM_TO_COMPILER_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalVMToInterpreter.cpp	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+#include "precompiled.hpp"
+#include "graal/graalVMToInterpreter.hpp"
+#include "graal/graalInterpreterToVM.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "graal/graalCompiler.hpp"
+
+#ifdef HIGH_LEVEL_INTERPRETER
+
+// those are *global* handles
+jobject VMToInterpreter::_interpreterPermObject = NULL;
+jobject VMToInterpreter::_interpreterPermKlass = NULL;
+
+class JavaArgumentBoxer : public SignatureIterator {
+ protected:
+  JavaCallArguments* _args;
+  Thread* _thread;
+  objArrayHandle _obj_array;
+  int _index;
+  int _position;
+
+ public:
+  JavaArgumentBoxer(Symbol* signature, objArrayHandle obj_array, JavaCallArguments* args, bool is_static, TRAPS) : SignatureIterator(signature) {
+    _obj_array = obj_array;
+    _args = args;
+    _index = _position = 0;
+    _thread = THREAD;
+    if (!is_static) {
+      push(next_object(T_OBJECT));
+    }
+    iterate();
+    assert(_index == _obj_array->length(), "arg count mismatch with signature");
+  }
+
+  inline void do_bool()   {
+    if (!is_return_type()) {
+      jvalue value;
+      value.z = (jboolean)_args->get_int(_position);
+      push(java_lang_boxing_object::create(T_BOOLEAN, &value, _thread));
+    }
+  }
+  inline void do_char()   {
+    if (!is_return_type()) {
+      jvalue value;
+      value.c = (jchar)_args->get_int(_position);
+      push(java_lang_boxing_object::create(T_CHAR, &value, _thread));
+    }
+  }
+  inline void do_short()  {
+    if (!is_return_type()) {
+      jvalue value;
+      value.s = (jshort)_args->get_int(_position);
+      push(java_lang_boxing_object::create(T_SHORT, &value, _thread));
+    }
+  }
+  inline void do_byte()   {
+    if (!is_return_type()) {
+      jvalue value;
+      value.b = (jbyte)_args->get_int(_position);
+      push(java_lang_boxing_object::create(T_BYTE, &value, _thread));
+    }
+  }
+  inline void do_int()    {
+    if (!is_return_type()) {
+      jvalue value;
+      value.i = (jint)_args->get_int(_position);
+      push(java_lang_boxing_object::create(T_INT, &value, _thread));
+    }
+  }
+
+  inline void do_long()   {
+    if (!is_return_type()) {
+      jvalue value;
+      value.j = (jlong)_args->get_long(_position);
+      push(java_lang_boxing_object::create(T_LONG, &value, _thread));
+    }
+  }
+
+  inline void do_float()  {
+    if (!is_return_type()) {
+      jvalue value;
+      value.f = (jfloat)_args->get_float(_position);
+      push(java_lang_boxing_object::create(T_FLOAT, &value, _thread));
+    }
+  }
+
+  inline void do_double() {
+    if (!is_return_type()) {
+      jvalue value;
+      value.d = (jdouble)_args->get_double(_position);
+      push(java_lang_boxing_object::create(T_DOUBLE, &value, _thread));
+    }
+  }
+
+  inline void do_object(int begin, int end) { if (!is_return_type()) push(next_object(T_OBJECT)); }
+  inline void do_array(int begin, int end)  { if (!is_return_type()) push(next_object(T_ARRAY)); }
+  inline void do_void()                     { }
+  
+  inline oop next_object(BasicType type) {
+    assert(type == T_OBJECT || type == T_ARRAY, "must be");
+    return *(_args->get_raw_oop(_position));
+  }
+  
+  inline void push(oop obj) {
+    _obj_array->obj_at_put(_index, obj);
+    _index++;
+  }
+};
+
+bool VMToInterpreter::allocate_interpreter(const char* interpreter_class_name, const char* interpreter_arguments, TRAPS) {
+  assert(_interpreterPermObject == NULL && _interpreterPermKlass == NULL, "no need to allocate twice");
+
+  HandleMark hm;
+  // load the interpreter class using its fully qualified class name
+  Symbol* class_name = SymbolTable::lookup(interpreter_class_name, (int)strlen(interpreter_class_name), CHECK_false);
+  instanceKlassHandle interpreter_klass = SystemDictionary::resolve_or_null(class_name, SystemDictionary::java_system_loader(), NULL, CHECK_false);
+  if (interpreter_klass.is_null()) {
+    tty->print_cr("Could not load HighLevelInterpreterClass '%s'", interpreter_class_name);
+    return false;
+  }
+
+  // allocate an interpreter instance
+  interpreter_klass->initialize(CHECK_false);
+  instanceHandle interpreter_instance = interpreter_klass->allocate_instance_handle(CHECK_false);
+  
+  // initialize the interpreter instance
+  Handle args;
+  if (interpreter_arguments != NULL) {
+    args = java_lang_String::create_from_platform_dependent_str(interpreter_arguments, CHECK_false);
+  }
+
+  JavaValue result(T_BOOLEAN);
+  JavaCalls::call_virtual(&result, interpreter_instance, interpreter_klass, vmSymbols::initialize_name(), vmSymbols::setOption_signature(), args, CHECK_false);
+  if (result.get_jboolean() != JNI_TRUE) {
+    tty->print_cr("Could not invoke '%s::initialize(String)'", interpreter_class_name);
+    return false;
+  }
+
+  // store the instance globally and keep it alive
+  _interpreterPermObject = JNIHandles::make_global(interpreter_instance);
+  _interpreterPermKlass = JNIHandles::make_global(interpreter_klass);
+
+  // register the native functions that are needed by the interpreter
+  {
+    assert(THREAD->is_Java_thread(), "must be");
+    JavaThread* thread = (JavaThread*) THREAD;
+    ThreadToNativeFromVM trans(thread);
+    JNIEnv *env = thread->jni_environment();
+    jclass klass = env->FindClass("com/oracle/graal/hotspot/HotSpotRuntimeInterpreterInterface");
+    if (klass == NULL) {
+      tty->print_cr("Could not find class HotSpotRuntimeInterpreterInterface");
+      return false;
+    }
+    env->RegisterNatives(klass, InterpreterToVM_methods, InterpreterToVM_methods_count());
+    if (thread->has_pending_exception()) {
+      tty->print_cr("Could not register HotSpotRuntimeInterpreterInterface native methods");
+      return false;
+    }
+  }
+
+  return true;
+}
+
+Handle VMToInterpreter::interpreter_instance() {
+  return Handle(JNIHandles::resolve_non_null(_interpreterPermObject));
+}
+
+KlassHandle VMToInterpreter::interpreter_klass() {
+  return KlassHandle(JNIHandles::resolve_non_null(_interpreterPermKlass));
+}
+
+void VMToInterpreter::execute(JavaValue* result, methodHandle* m, JavaCallArguments* args, BasicType expected_result_type, TRAPS) {
+  assert(interpreter_instance().not_null(), "must be allocated before the first call");
+  assert(THREAD->is_Java_thread(), "must be");
+  assert(m != NULL, "must be");
+  assert(args != NULL, "must be");
+
+  JavaThread* thread = (JavaThread*)THREAD;
+  methodHandle method = *m;
+  int parameter_count = ArgumentCount(method->signature()).size() + (method->is_static() ? 0 : 1);
+  objArrayHandle args_array = oopFactory::new_objArray(SystemDictionary::Object_klass(), parameter_count, CHECK);
+  JavaArgumentBoxer jab(method->signature(), args_array, args, method->is_static(), thread);
+  Handle hotspot_method = GraalCompiler::createHotSpotResolvedJavaMethod(method, CHECK);
+
+  JavaValue boxed_result(T_OBJECT);
+  JavaCallArguments boxed_args;
+  boxed_args.set_receiver(interpreter_instance());
+  boxed_args.push_oop(hotspot_method);
+  boxed_args.push_oop(args_array);
+  
+#ifndef PRODUCT
+  if (PrintHighLevelInterpreterVMTransitions) {
+    ResourceMark m;
+    tty->print_cr("VM -> high level interpreter (%s)", method->name_and_sig_as_C_string());
+  }
+#endif
+  
+  thread->set_high_level_interpreter_in_vm(false);
+  JavaCalls::call_virtual(&boxed_result, interpreter_klass(), vmSymbols::interpreter_execute_name(), vmSymbols::interpreter_execute_signature(), &boxed_args, thread);
+  thread->set_high_level_interpreter_in_vm(true);
+  
+#ifndef PRODUCT
+  if (PrintHighLevelInterpreterVMTransitions) {
+    ResourceMark m;
+    tty->print_cr("High level interpreter (%s) -> VM", method->name_and_sig_as_C_string());
+  }
+#endif
+  
+  if (HAS_PENDING_EXCEPTION) {
+    return;
+  }
+
+  // unbox the result if necessary
+  if (is_java_primitive(expected_result_type)) {
+    unbox_primitive(&boxed_result, result);
+  } else if (expected_result_type == T_OBJECT || expected_result_type == T_ARRAY) {
+    result->set_jobject(boxed_result.get_jobject());
+  }
+}
+
+void VMToInterpreter::unbox_primitive(JavaValue* boxed, JavaValue* result) {
+  oop box = JNIHandles::resolve(boxed->get_jobject());
+
+  jvalue value;
+  BasicType type = java_lang_boxing_object::get_value(box, &value);
+    switch (type) {
+    case T_BOOLEAN:
+      result->set_jint(value.z);
+      break;
+    case T_CHAR:
+      result->set_jint(value.c);
+      break;
+    case T_FLOAT:
+      result->set_jfloat(value.f);
+      break;
+    case T_DOUBLE:
+      result->set_jdouble(value.d);
+      break;
+    case T_BYTE:
+      result->set_jint(value.b);
+      break;
+    case T_SHORT:
+      result->set_jint(value.s);
+      break;
+    case T_INT:
+      result->set_jint(value.i);
+      break;
+    case T_LONG:
+      result->set_jlong(value.j);
+      break;
+    default:
+      ShouldNotReachHere();
+      break;
+  }
+}
+
+#endif // HIGH_LEVEL_INTERPRETER
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/graal/graalVMToInterpreter.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+#include "memory/allocation.hpp"
+#include "oops/oop.hpp"
+#include "runtime/handles.hpp"
+#include "runtime/thread.hpp"
+#include "classfile/javaClasses.hpp"
+#include "runtime/jniHandles.hpp"
+#include "runtime/javaCalls.hpp"
+
+#ifdef HIGH_LEVEL_INTERPRETER
+#ifndef SHARE_VM_GRAAL_GRAAL_VM_TO_INTERPRETER_HPP
+#define SHARE_VM_GRAAL_GRAAL_VM_TO_INTERPRETER_HPP
+
+class VMToInterpreter : public AllStatic {
+
+private:
+  static jobject _interpreterPermObject;
+  static jobject _interpreterPermKlass;
+
+  static Handle interpreter_instance();
+  static KlassHandle interpreter_klass();
+  static void unbox_primitive(JavaValue* boxed, JavaValue* result);
+
+public:
+  static bool allocate_interpreter(const char* interpreter_class_name, const char* interpreter_arguments, TRAPS);
+ 
+  // invokes the interpreter method execute(ResolvedJavaMethod method, Object... arguments)
+  static void execute(JavaValue* result, methodHandle* m, JavaCallArguments* args, BasicType expected_result_type, TRAPS);
+};
+
+#endif // SHARE_VM_GRAAL_GRAAL_VM_TO_INTERPRETER_HPP
+#endif // HIGH_LEVEL_INTERPRETER
--- a/src/share/vm/graal/graalVmIds.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/graal/graalVmIds.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -21,6 +21,9 @@
  * questions.
  */
 
+#ifndef SHARE_VM_GRAAL_GRAAL_VM_IDS_HPP
+#define SHARE_VM_GRAAL_GRAAL_VM_IDS_HPP
+
 #include "memory/allocation.hpp"
 #include "utilities/growableArray.hpp"
 #include "oops/oop.hpp"
@@ -80,3 +83,4 @@
   return obj->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG));
 }
 
+#endif // SHARE_VM_GRAAL_GRAAL_VM_IDS_HPP
--- a/src/share/vm/prims/jni.cpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/prims/jni.cpp	Thu Jul 05 16:54:45 2012 +0200
@@ -32,6 +32,9 @@
 #ifdef GRAAL
 #include "graal/graalCompiler.hpp"
 #endif
+#ifdef HIGH_LEVEL_INTERPRETER
+#include "graal/graalVMToInterpreter.hpp"
+#endif
 #ifndef SERIALGC
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
 #endif // SERIALGC
@@ -1317,6 +1320,7 @@
 }
 
 
+static bool first_time_InvokeMain = true;
 
 static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) {
   methodHandle method(THREAD, JNIHandles::resolve_jmethod_id(method_id));
@@ -1325,6 +1329,8 @@
   // the jni parser
   ResourceMark rm(THREAD);
   int number_of_parameters = method->size_of_parameters();
+
+  // Invoke the method. Result is returned as oop.
   JavaCallArguments java_args(number_of_parameters);
   args->set_java_argument_object(&java_args);
 
@@ -1332,16 +1338,35 @@
 
   // Fill out JavaCallArguments object
   args->iterate( Fingerprinter(method).fingerprint() );
-  // Initialize result type
+  // Initialize result type (must be done after args->iterate())
   result->set_type(args->get_ret_type());
 
-  // Invoke the method. Result is returned as oop.
+#ifdef HIGH_LEVEL_INTERPRETER
+  // TODO (chaeubl): this is quite a hack. The launcher should take care about that instead.
+  bool invoked_main_method = false;
+  if (HighLevelInterpreterClass != NULL && first_time_InvokeMain && method->name() == vmSymbols::main_name() && method->result_type() == T_VOID) {
+    assert(THREAD->is_Java_thread(), "other threads must not call into java");
+    JavaThread* thread = (JavaThread*)THREAD;
+    first_time_InvokeMain = false;
+    invoked_main_method = true;
+    thread->set_high_level_interpreter_in_vm(true);
+  }
+#endif
+
   JavaCalls::call(result, method, &java_args, CHECK);
 
   // Convert result
   if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) {
     result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject()));
   }
+
+#ifdef HIGH_LEVEL_INTERPRETER
+  if (invoked_main_method) {
+    assert(THREAD->is_Java_thread(), "other threads must not call into java");
+    JavaThread* thread = (JavaThread*)THREAD;
+    thread->set_high_level_interpreter_in_vm(false);
+  }
+#endif
 }
 
 
@@ -5144,6 +5169,16 @@
       compiler->initialize();
 #endif
 
+#ifdef HIGH_LEVEL_INTERPRETER
+      if (HighLevelInterpreterClass != NULL) {
+        bool result = VMToInterpreter::allocate_interpreter(HighLevelInterpreterClass, HighLevelInterpreterArguments, thread);
+        if (!result) {
+          vm_abort(false);
+          return JNI_ERR;
+        }
+      }
+#endif
+
     // Tracks the time application was running before GC
     RuntimeService::record_application_start();
 
--- a/src/share/vm/runtime/deoptimization.cpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/runtime/deoptimization.cpp	Thu Jul 05 16:54:45 2012 +0200
@@ -1291,6 +1291,7 @@
     
     if (TraceDeoptimization) {
       tty->print_cr("  bci=%d pc=%d, relative_pc=%d, method=%s", trap_scope->bci(), fr.pc(), fr.pc() - nm->code_begin(), trap_scope->method()->name()->as_C_string());
+#ifdef GRAAL
       if (thread->graal_deopt_info() != NULL) {
         oop deopt_info = thread->graal_deopt_info();
         if (java_lang_String::is_instance(deopt_info)) {
@@ -1303,6 +1304,7 @@
         }
         thread->set_graal_deopt_info(NULL);
       }
+#endif
     }
 
     methodHandle    trap_method = trap_scope->method();
--- a/src/share/vm/runtime/globals.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/runtime/globals.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -631,6 +631,15 @@
   develop(bool, InlineAtomicLong, true,                                     \
           "inline sun.misc.AtomicLong")                                     \
                                                                             \
+  product(ccstr, HighLevelInterpreterClass, NULL,                           \
+          "fully qualified class name of the high-level interpreter")       \
+                                                                            \
+  product(ccstr, HighLevelInterpreterArguments, NULL,                       \
+          "arguments that are passed to the high-level interpreter")        \
+                                                                            \
+  notproduct(bool, PrintHighLevelInterpreterVMTransitions, false,           \
+          "print transitions between VM and high-level interpreter")        \
+                                                                            \
   develop(bool, InlineThreadNatives, true,                                  \
           "inline Thread.currentThread, etc")                               \
                                                                             \
--- a/src/share/vm/runtime/javaCalls.cpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/runtime/javaCalls.cpp	Thu Jul 05 16:54:45 2012 +0200
@@ -39,6 +39,9 @@
 #include "runtime/mutexLocker.hpp"
 #include "runtime/signature.hpp"
 #include "runtime/stubRoutines.hpp"
+#ifdef HIGH_LEVEL_INTERPRETER
+# include "graal/graalVMToInterpreter.hpp"
+#endif
 #ifdef TARGET_OS_FAMILY_linux
 # include "thread_linux.inline.hpp"
 #endif
@@ -437,7 +440,14 @@
     ShouldNotReachHere();
 #endif
   }
-
+  
+#ifdef HIGH_LEVEL_INTERPRETER
+  if (thread->high_level_interpreter_in_vm() && !method->is_native() && Interpreter::contains(entry_point)) {
+    assert(nm == NULL || !nm->is_alive(), "otherwise nm should be invoked");
+    VMToInterpreter::execute(result, m, args, result->get_type(), thread);
+    oop_result_flag = false; // result already holds the correct value
+  } else
+#endif
   // do call
   { JavaCallWrapper link(method, receiver, result, CHECK);
     { HandleMark hm(thread);  // HandleMark used by HandleMarkCleaner
@@ -473,7 +483,6 @@
   }
 }
 
-
 //--------------------------------------------------------------------------------------
 // Implementation of JavaCallArguments
 
--- a/src/share/vm/runtime/javaCalls.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/runtime/javaCalls.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -159,6 +159,12 @@
   inline void push_float(float f)   { _is_oop[_size] = false;
                                JNITypes::put_float(f, _value, _size); }
 
+  inline oop* get_raw_oop(int& pos)   { return (oop*)JNITypes::get_obj(_value, pos); }
+  inline jint get_int(int& pos)       { return JNITypes::get_int(_value, pos); }
+  inline jdouble get_double(int& pos) { return JNITypes::get_double(_value, pos); }
+  inline jlong get_long(int& pos)     { return JNITypes::get_long(_value, pos); }
+  inline jfloat get_float(int& pos)   { return JNITypes::get_float(_value, pos); }
+
   // receiver
   Handle receiver() {
     assert(_size > 0, "must at least be one argument");
@@ -191,7 +197,7 @@
 
 class JavaCalls: AllStatic {
   static void call_helper(JavaValue* result, methodHandle* method, nmethod* nm, JavaCallArguments* args, TRAPS);
- public:
+public:
   // Optimized Constuctor call
   static void call_default_constructor(JavaThread* thread, methodHandle method, Handle receiver, TRAPS);
 
--- a/src/share/vm/runtime/thread.cpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/runtime/thread.cpp	Thu Jul 05 16:54:45 2012 +0200
@@ -1303,8 +1303,13 @@
   _in_deopt_handler = 0;
   _doing_unsafe_access = false;
   _stack_guard_state = stack_guard_unused;
+#ifdef GRAAL
   _graal_deopt_info = NULL;
   _graal_alternate_call_target = NULL;
+#endif
+#ifdef HIGH_LEVEL_INTERPRETER
+  _high_level_interpreter_in_vm = false;
+#endif
   _exception_oop = NULL;
   _exception_pc  = 0;
   _exception_handler_pc = 0;
@@ -2622,7 +2627,9 @@
   f->do_oop((oop*) &_threadObj);
   f->do_oop((oop*) &_vm_result);
   f->do_oop((oop*) &_vm_result_2);
+#ifdef GRAAL
   f->do_oop((oop*) &_graal_deopt_info);
+#endif
   f->do_oop((oop*) &_exception_oop);
   f->do_oop((oop*) &_pending_async_exception);
 
--- a/src/share/vm/runtime/thread.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/runtime/thread.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -866,11 +866,16 @@
 
  private:
 
+#ifdef GRAAL
   // graal needs some place to put the dimensions
-  jint graal_multinewarray_storage[256];
+  jint _graal_multinewarray_storage[256];
 
   volatile oop _graal_deopt_info;
   address _graal_alternate_call_target;
+#endif
+#ifdef HIGH_LEVEL_INTERPRETER
+  bool _high_level_interpreter_in_vm;
+#endif
 
   StackGuardState        _stack_guard_state;
 
@@ -1234,10 +1239,16 @@
   MemRegion deferred_card_mark() const           { return _deferred_card_mark; }
   void set_deferred_card_mark(MemRegion mr)      { _deferred_card_mark = mr;   }
 
+#ifdef GRAAL
   oop      graal_deopt_info() const              { return _graal_deopt_info; }
   void set_graal_deopt_info(oop o)               { _graal_deopt_info = o; }
-
+  
   void set_graal_alternate_call_target(address a) { _graal_alternate_call_target = a; }
+#endif
+#ifdef HIGH_LEVEL_INTERPRETER
+  bool high_level_interpreter_in_vm()            { return _high_level_interpreter_in_vm; }
+  void set_high_level_interpreter_in_vm(bool value) { _high_level_interpreter_in_vm = value; }
+#endif
 
   // Exception handling for compiled methods
   oop      exception_oop() const                 { return _exception_oop; }
@@ -1318,15 +1329,20 @@
   static ByteSize thread_state_offset()          { return byte_offset_of(JavaThread, _thread_state        ); }
   static ByteSize saved_exception_pc_offset()    { return byte_offset_of(JavaThread, _saved_exception_pc  ); }
   static ByteSize osthread_offset()              { return byte_offset_of(JavaThread, _osthread            ); }
+#ifdef GRAAL
   static ByteSize graal_deopt_info_offset()      { return byte_offset_of(JavaThread, _graal_deopt_info    ); }
   static ByteSize graal_alternate_call_target_offset() { return byte_offset_of(JavaThread, _graal_alternate_call_target); }
+  static ByteSize graal_multinewarray_storage_offset() { return byte_offset_of(JavaThread, _graal_multinewarray_storage); }
+#endif
+#ifdef HIGH_LEVEL_INTERPRETER
+  static ByteSize high_level_interpreter_in_vm_offset() { return byte_offset_of(JavaThread, _high_level_interpreter_in_vm); }
+#endif
   static ByteSize exception_oop_offset()         { return byte_offset_of(JavaThread, _exception_oop       ); }
   static ByteSize exception_pc_offset()          { return byte_offset_of(JavaThread, _exception_pc        ); }
   static ByteSize exception_handler_pc_offset()  { return byte_offset_of(JavaThread, _exception_handler_pc); }
   static ByteSize is_method_handle_return_offset() { return byte_offset_of(JavaThread, _is_method_handle_return); }
   static ByteSize stack_guard_state_offset()     { return byte_offset_of(JavaThread, _stack_guard_state   ); }
   static ByteSize suspend_flags_offset()         { return byte_offset_of(JavaThread, _suspend_flags       ); }
-  static ByteSize graal_multinewarray_storage_offset() { return byte_offset_of(JavaThread, graal_multinewarray_storage); }
 
   static ByteSize do_not_unlock_if_synchronized_offset() { return byte_offset_of(JavaThread, _do_not_unlock_if_synchronized); }
   static ByteSize should_post_on_exceptions_flag_offset() {
--- a/src/share/vm/utilities/globalDefinitions.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/utilities/globalDefinitions.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -106,9 +106,9 @@
 // log2_intptr(sizeof(class JavaThread)) - log2_intptr(64);
 // see os::set_memory_serialize_page()
 #ifdef _LP64
-const int SerializePageShiftCount = 5;
+const int SerializePageShiftCount = GRAAL_ONLY(5) NOT_GRAAL(4);
 #else
-const int SerializePageShiftCount = 4;
+const int SerializePageShiftCount = GRAAL_ONLY(4) NOT_GRAAL(3);
 #endif
 
 // An opaque struct of heap-word width, so that HeapWord* can be a generic
--- a/src/share/vm/utilities/macros.hpp	Thu Jul 05 16:54:00 2012 +0200
+++ b/src/share/vm/utilities/macros.hpp	Thu Jul 05 16:54:45 2012 +0200
@@ -80,7 +80,15 @@
 #else
 #define GRAAL_ONLY(code)
 #define NOT_GRAAL(code) code
-#endif
+#endif // GRAAL
+
+#ifdef HIGH_LEVEL_INTERPRETER
+#define HIGH_LEVEL_INTERPRETER_ONLY(code) code
+#define NOT_HIGH_LEVEL_INTERPRETER(code)
+#else
+#define HIGH_LEVEL_INTERPRETER_ONLY(code)
+#define NOT_HIGH_LEVEL_INTERPRETER(code) code
+#endif // HIGH_LEVEL_INTERPRETER
 
 #ifdef TIERED
 #define TIERED_ONLY(code) code