changeset 5751:99e186e7ad62

Merge
author Gilles Duboscq <duboscq@ssw.jku.at>
date Wed, 04 Jul 2012 13:55:52 +0200
parents 30876d0bb92d (current diff) 12706c5b39bc (diff)
children f043ecb70d3e
files graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/VMAdapter.java
diffstat 37 files changed, 1326 insertions(+), 559 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/Interpreter.java	Wed Jul 04 13:55:03 2012 +0200
+++ b/graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/Interpreter.java	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:52 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.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Wed Jul 04 13:55:03 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Jul 04 13:55:52 2012 +0200
@@ -61,7 +61,7 @@
     public int instanceHeaderPrototypeOffset;
     public int threadExceptionOopOffset;
     public int threadExceptionPcOffset;
-    public int threadMultiNewArrayStorage;
+    public int threadMultiNewArrayStorageOffset;
     public long cardtableStartAddress;
     public int cardtableShift;
     public long safepointPollingAddress;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java	Wed Jul 04 13:55:03 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java	Wed Jul 04 13:55:52 2012 +0200
@@ -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.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java	Wed Jul 04 13:55:03 2012 +0200
+++ b/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java	Wed Jul 04 13:55:52 2012 +0200
@@ -25,6 +25,7 @@
 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.*;
@@ -49,7 +50,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 +59,32 @@
 
     private InterpreterFrame callFrame;
 
-    //TODO try to remove this reference
-    private ExceptionHandler catchAllExceptionHandler;
+    private Map<ResolvedJavaMethod, MethodRedirectionInfo> methodDelegates;
 
-    private final Map<ResolvedJavaMethod, InterpreterCallable> methodDelegates = new HashMap<>();
-
-    private int maxStackFrames = DEFAULT_MAX_STACK_SIZE;
+    private int maxStackFrames;
     private int stackFrameDepth;
 
-    private final ResolvedJavaMethod rootMethod;
-    private final VMAdapter vm;
+    private ResolvedJavaMethod rootMethod;
+    private RuntimeInterpreterInterface runtimeInterface;
+    private MetaAccessProvider metaAccessProvider;
+
+    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,19 +94,18 @@
         }
     }
 
-
     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));
+        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 base, Object[] arguments) throws Throwable {
-               StackTraceElement[] elements = getBackTrace(caller, (Throwable) base);
+           public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable {
+               StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]);
                if (elements != null) {
                    return elements.length;
                }
@@ -110,8 +114,8 @@
        });
        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);
+           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) {
@@ -123,6 +127,12 @@
        });
     }
 
+    @SuppressWarnings("unused")
+    private boolean parseArguments(String stringArgs) {
+        // TODO: parse the arguments
+        return true;
+    }
+
     public void setMaxStackFrames(int maxStackSize) {
         this.maxStackFrames = maxStackSize;
     }
@@ -132,53 +142,55 @@
     }
 
     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.");
-        }
-
-        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; i < 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) {
+            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 {
@@ -392,28 +404,28 @@
                 frame.pushObject(frame.getObject(frame.resolveLocalIndex(3)));
                 break;
             case Bytecodes.IALOAD         :
-                frame.pushInt(vm.getArrayInt(frame.popInt(), frame.popObject()));
+                frame.pushInt(runtimeInterface.getArrayInt(frame.popInt(), frame.popObject()));
                 break;
             case Bytecodes.LALOAD         :
-                frame.pushLong(vm.getArrayLong(frame.popInt(), frame.popObject()));
+                frame.pushLong(runtimeInterface.getArrayLong(frame.popInt(), frame.popObject()));
                 break;
             case Bytecodes.FALOAD         :
-                frame.pushFloat(vm.getArrayFloat(frame.popInt(), frame.popObject()));
+                frame.pushFloat(runtimeInterface.getArrayFloat(frame.popInt(), frame.popObject()));
                 break;
             case Bytecodes.DALOAD         :
-                frame.pushDouble(vm.getArrayDouble(frame.popInt(), frame.popObject()));
+                frame.pushDouble(runtimeInterface.getArrayDouble(frame.popInt(), frame.popObject()));
                 break;
             case Bytecodes.AALOAD         :
-                frame.pushObject(vm.getArrayObject(frame.popInt(), frame.popObject()));
+                frame.pushObject(runtimeInterface.getArrayObject(frame.popInt(), frame.popObject()));
                 break;
             case Bytecodes.BALOAD         :
-                frame.pushInt(vm.getArrayByte(frame.popInt(), frame.popObject()));
+                frame.pushInt(runtimeInterface.getArrayByte(frame.popInt(), frame.popObject()));
                 break;
             case Bytecodes.CALOAD         :
-                frame.pushInt(vm.getArrayChar(frame.popInt(), frame.popObject()));
+                frame.pushInt(runtimeInterface.getArrayChar(frame.popInt(), frame.popObject()));
                 break;
              case Bytecodes.SALOAD:
-                frame.pushInt(vm.getArrayShort(frame.popInt(), frame.popObject()));
+                frame.pushInt(runtimeInterface.getArrayShort(frame.popInt(), frame.popObject()));
                 break;
             case Bytecodes.ISTORE:
                 frame.setInt(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popInt());
@@ -491,28 +503,28 @@
                 frame.setObject(frame.resolveLocalIndex(3), frame.popObject());
                 break;
             case Bytecodes.IASTORE        :
-                vm.setArrayInt(frame.popInt(), frame.popInt(), frame.popObject());
+                runtimeInterface.setArrayInt(frame.popInt(), frame.popInt(), frame.popObject());
                 break;
             case Bytecodes.LASTORE        :
-                vm.setArrayLong(frame.popLong(), frame.popInt(), frame.popObject());
+                runtimeInterface.setArrayLong(frame.popLong(), frame.popInt(), frame.popObject());
                 break;
             case Bytecodes.FASTORE        :
-                vm.setArrayFloat(frame.popFloat(), frame.popInt(), frame.popObject());
+                runtimeInterface.setArrayFloat(frame.popFloat(), frame.popInt(), frame.popObject());
                 break;
             case Bytecodes.DASTORE        :
-                vm.setArrayDouble(frame.popDouble(), frame.popInt(), frame.popObject());
+                runtimeInterface.setArrayDouble(frame.popDouble(), frame.popInt(), frame.popObject());
                 break;
             case Bytecodes.AASTORE        :
-                vm.setArrayObject(frame.popObject(), frame.popInt(), frame.popObject());
+                runtimeInterface.setArrayObject(frame.popObject(), frame.popInt(), frame.popObject());
                 break;
             case Bytecodes.BASTORE        :
-                vm.setArrayByte((byte) frame.popInt(), frame.popInt(), frame.popObject());
+                runtimeInterface.setArrayByte((byte) frame.popInt(), frame.popInt(), frame.popObject());
                 break;
             case Bytecodes.CASTORE        :
-                vm.setArrayChar((char) frame.popInt(), frame.popInt(), frame.popObject());
+                runtimeInterface.setArrayChar((char) frame.popInt(), frame.popInt(), frame.popObject());
                 break;
             case Bytecodes.SASTORE        :
-                vm.setArrayShort((short) frame.popInt(), frame.popInt(), frame.popObject());
+                runtimeInterface.setArrayShort((short) frame.popInt(), frame.popInt(), frame.popObject());
                 break;
             case Bytecodes.POP            :
                 frame.popVoid(1);
@@ -849,7 +861,7 @@
                 }
                 return CALL;
             case Bytecodes.XXXUNUSEDXXX   :
-                assert false : "unused bytecode used. behaviour unspecfied.";
+                assert false : "unused bytecode used. behaviour unspecified.";
                 // nop
                 break;
             case Bytecodes.NEW            :
@@ -873,10 +885,10 @@
                 instanceOf(frame, bs.readCPI());
                 break;
             case Bytecodes.MONITORENTER   :
-                vm.monitorEnter(frame.popObject());
+                runtimeInterface.monitorEnter(frame.popObject());
                 break;
             case Bytecodes.MONITOREXIT    :
-                vm.monitorExit(frame.popObject());
+                runtimeInterface.monitorExit(frame.popObject());
                 break;
             case Bytecodes.WIDE           :
                 assert false;
@@ -912,11 +924,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);
@@ -940,11 +947,11 @@
 
 
     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,19 +959,18 @@
     }
 
     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
@@ -997,36 +1003,33 @@
                     traceOp("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");
             }
             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);
                 }
             }
         }
@@ -1196,7 +1199,7 @@
     }
 
     private ResolvedJavaType resolveType(InterpreterFrame frame, Class<?> javaClass) {
-        return vm.getRuntime().getResolvedJavaType(javaClass).resolve(frame.getMethod().holder());
+        return metaAccessProvider.getResolvedJavaType(javaClass).resolve(frame.getMethod().holder());
     }
 
     private ResolvedJavaMethod resolveMethod(InterpreterFrame frame, int opcode, char cpi) {
@@ -1319,104 +1322,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 {
+    private InterpreterFrame invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object receiver) throws Throwable {
         if (stackFrameDepth >= 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());
@@ -1448,7 +1438,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) {
@@ -1471,19 +1461,19 @@
             case Char :
             case Short :
             case Int :
-                vm.setFieldInt(frame.popInt(), null, field);
+                runtimeInterface.setFieldInt(frame.popInt(), null, field);
                 break;
             case Double :
-                vm.setFieldDouble(frame.popDouble(), null, field);
+                runtimeInterface.setFieldDouble(frame.popDouble(), null, field);
                 break;
             case Float :
-                vm.setFieldFloat(frame.popFloat(), null, field);
+                runtimeInterface.setFieldFloat(frame.popFloat(), null, field);
                 break;
             case Long :
-                vm.setFieldLong(frame.popLong(), null, field);
+                runtimeInterface.setFieldLong(frame.popLong(), null, field);
                 break;
             case Object :
-                vm.setField(frame.popObject(), null, field);
+                runtimeInterface.setFieldObject(frame.popObject(), null, field);
                 break;
             default :
                 assert false : "unexpected case";
@@ -1497,19 +1487,19 @@
             case Char :
             case Short :
             case Int :
-                vm.setFieldInt(frame.popInt(), nullCheck(frame.popObject()), field);
+                runtimeInterface.setFieldInt(frame.popInt(), nullCheck(frame.popObject()), field);
                 break;
             case Double :
-                vm.setFieldDouble(frame.popDouble(), nullCheck(frame.popObject()), field);
+                runtimeInterface.setFieldDouble(frame.popDouble(), nullCheck(frame.popObject()), field);
                 break;
             case Float :
-                vm.setFieldFloat(frame.popFloat(), nullCheck(frame.popObject()), field);
+                runtimeInterface.setFieldFloat(frame.popFloat(), nullCheck(frame.popObject()), field);
                 break;
             case Long :
-                vm.setFieldLong(frame.popLong(), nullCheck(frame.popObject()), field);
+                runtimeInterface.setFieldLong(frame.popLong(), nullCheck(frame.popObject()), field);
                 break;
             case Object :
-                vm.setField(frame.popObject(), nullCheck(frame.popObject()), field);
+                runtimeInterface.setFieldObject(frame.popObject(), nullCheck(frame.popObject()), field);
                 break;
             default :
                 assert false : "unexpected case";
@@ -1520,23 +1510,31 @@
         ResolvedJavaField field = resolveField(frame, opcode, cpi);
         switch (field.kind()) {
             case Boolean :
+                frame.pushInt(runtimeInterface.getFieldBoolean(base, field) ? 1 : 0);
+                break;
             case Byte :
+                frame.pushInt(runtimeInterface.getFieldByte(base, field));
+                break;
             case Char :
+                frame.pushInt(runtimeInterface.getFieldChar(base, field));
+                break;
             case Short :
+                frame.pushInt(runtimeInterface.getFieldShort(base, field));
+                break;
             case Int :
-                frame.pushInt(vm.getFieldInt(base, field));
+                frame.pushInt(runtimeInterface.getFieldInt(base, field));
                 break;
             case Double :
-                frame.pushDouble(vm.getFieldDouble(base, field));
+                frame.pushDouble(runtimeInterface.getFieldDouble(base, field));
                 break;
             case Float :
-                frame.pushFloat(vm.getFieldFloat(base, field));
+                frame.pushFloat(runtimeInterface.getFieldFloat(base, field));
                 break;
             case Long :
-                frame.pushLong(vm.getFieldLong(base, field));
+                frame.pushLong(runtimeInterface.getFieldLong(base, field));
                 break;
             case Object :
-                frame.pushObject(vm.getField(base, field));
+                frame.pushObject(runtimeInterface.getFieldObject(base, field));
                 break;
             default :
                 assert false : "unexpected case";
@@ -1611,7 +1609,7 @@
 
     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);
         }
@@ -1655,4 +1653,31 @@
         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	Wed Jul 04 13:55:03 2012 +0200
+++ b/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterCallable.java	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterFrame.java	Wed Jul 04 13:55:52 2012 +0200
@@ -245,6 +245,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	Wed Jul 04 13:55:03 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;
-    }
-
-
-}
--- a/src/cpu/x86/vm/jniTypes_x86.hpp	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/cpu/x86/vm/jniTypes_x86.hpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Wed Jul 04 13:55:52 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/vm/classfile/javaClasses.hpp	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/classfile/javaClasses.hpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Wed Jul 04 13:55:52 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.hpp	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/graal/graalCompiler.hpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Jul 04 13:55:52 2012 +0200
@@ -802,7 +802,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()));
@@ -966,48 +966,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 +979,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);
--- a/src/share/vm/graal/graalCompilerToVM.hpp	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.hpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/graal/graalEnv.hpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Wed Jul 04 13:55:52 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"
@@ -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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/graal/graalRuntime.hpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.hpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:52 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(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	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/graal/graalVmIds.hpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/prims/jni.cpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/runtime/deoptimization.cpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/runtime/globals.hpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/runtime/javaCalls.cpp	Wed Jul 04 13:55:52 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,13 @@
     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);
+  } else
+#endif
   // do call
   { JavaCallWrapper link(method, receiver, result, CHECK);
     { HandleMark hm(thread);  // HandleMark used by HandleMarkCleaner
@@ -473,7 +482,6 @@
   }
 }
 
-
 //--------------------------------------------------------------------------------------
 // Implementation of JavaCallArguments
 
--- a/src/share/vm/runtime/javaCalls.hpp	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/runtime/javaCalls.hpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/runtime/thread.cpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/runtime/thread.hpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/utilities/globalDefinitions.hpp	Wed Jul 04 13:55:52 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	Wed Jul 04 13:55:03 2012 +0200
+++ b/src/share/vm/utilities/macros.hpp	Wed Jul 04 13:55:52 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