changeset 7755:e8c71b8562e3

Merge
author Christian Humer <christian.humer@gmail.com>
date Mon, 11 Feb 2013 10:41:29 +0100
parents 3cec97eb3b5f (current diff) 52fd6491fca8 (diff)
children 859f7ec58a71 10f1c713f4f0
files graal/com.oracle.graal.api.interpreter/overview.html graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/Interpreter.java graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/RuntimeInterpreterInterface.java graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/VirtualMachineComponent.java graal/com.oracle.graal.api.test/src/com/oracle/graal/api/test/GraalTest.java graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/X86InstructionDecoder.java graal/com.oracle.graal.interpreter/overview.html graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/Frame.java graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterCallable.java graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterException.java graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterFrame.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewObjectArrayNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewPrimitiveArrayNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GlobalValueNumberingPhase.java
diffstat 150 files changed, 2783 insertions(+), 4425 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java	Mon Feb 11 10:41:29 2013 +0100
@@ -26,6 +26,8 @@
 import static com.oracle.graal.api.code.Register.RegisterFlag.*;
 import static com.oracle.graal.api.meta.Kind.*;
 
+import java.nio.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.Register.*;
 
@@ -109,7 +111,7 @@
     public AMD64() {
         super("AMD64",
               8,
-              ByteOrder.LittleEndian,
+              ByteOrder.LITTLE_ENDIAN,
               allRegisters,
               LOAD_STORE | STORE_STORE,
               1,
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java	Mon Feb 11 10:41:29 2013 +0100
@@ -22,9 +22,10 @@
  */
 package com.oracle.graal.api.code;
 
+import java.nio.*;
 import java.util.*;
 
-import com.oracle.graal.api.code.Register.*;
+import com.oracle.graal.api.code.Register.RegisterFlag;
 
 /**
  * Represents a CPU architecture, including information such as its endianness, CPU registers, word
@@ -33,13 +34,6 @@
 public abstract class Architecture {
 
     /**
-     * The endianness of the architecture.
-     */
-    public static enum ByteOrder {
-        LittleEndian, BigEndian
-    }
-
-    /**
      * The number of bits required in a bit map covering all the registers that may store
      * references. The bit position of a register in the map is the register's
      * {@linkplain Register#number number}.
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Mon Feb 11 10:41:29 2013 +0100
@@ -103,4 +103,9 @@
      * {@link CompilationResult}. A data patch is always created for an object constant.
      */
     boolean needsDataPatch(Constant constant);
+
+    /**
+     * Gets a description of the target architecture.
+     */
+    TargetDescription getTarget();
 }
--- a/graal/com.oracle.graal.api.interpreter/overview.html	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html>
-<head>
-<!--
-
-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.  Oracle designates this
-particular file as subject to the "Classpath" exception as provided
-by Oracle in the LICENSE file that accompanied this code.
-
-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.
--->
-
-</head>
-<body>
-
-Documentation for the <code>com.oracle.graal.api.interpreter</code> project.
-
-</body>
-</html>
--- a/graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/Interpreter.java	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +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.api.interpreter;
-
-import com.oracle.graal.api.meta.*;
-
-public interface Interpreter extends VirtualMachineComponent {
-
-    boolean initialize(String args);
-
-    Object execute(ResolvedJavaMethod method, Object... arguments) throws Throwable;
-}
--- a/graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/RuntimeInterpreterInterface.java	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +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.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);
-
-    Class<?> getMirror(ResolvedJavaType type);
-}
--- a/graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/VirtualMachineComponent.java	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.api.interpreter;
-
-public interface VirtualMachineComponent {
-
-    void setOption(String name, String value);
-}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java	Mon Feb 11 10:41:29 2013 +0100
@@ -39,5 +39,5 @@
     Unresolved,
     JavaSubroutineMismatch,
     ArithmeticException,
-    RuntimeConstraint,
+    RuntimeConstraint
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Mon Feb 11 10:41:29 2013 +0100
@@ -410,9 +410,9 @@
      * @return the annotation of type {@code annotationClass} (if any) for each formal parameter
      *         present
      */
+    @SuppressWarnings("unchecked")
     public static <T extends Annotation> T[] getParameterAnnotations(Class<T> annotationClass, ResolvedJavaMethod method) {
         Annotation[][] parameterAnnotations = method.getParameterAnnotations();
-        @SuppressWarnings("unchecked")
         T[] result = (T[]) Array.newInstance(annotationClass, parameterAnnotations.length);
         for (int i = 0; i < parameterAnnotations.length; i++) {
             for (Annotation a : parameterAnnotations[i]) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.test/src/com/oracle/graal/api/test/GraalAPITest.java	Mon Feb 11 10:41:29 2013 +0100
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.api.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.runtime.*;
+
+public class GraalAPITest {
+
+    @Test
+    public void testRuntimeAvailable() {
+        assertNotNull(Graal.getRuntime());
+        System.out.println(Graal.getRuntime().getClass());
+    }
+
+    @Test
+    public void testRuntimeNamed() {
+        assertNotNull(Graal.getRuntime().getName());
+        System.out.println(Graal.getRuntime().getName());
+    }
+}
--- a/graal/com.oracle.graal.api.test/src/com/oracle/graal/api/test/GraalTest.java	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.api.test;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.runtime.*;
-
-public class GraalTest {
-
-    @Test
-    public void testRuntimeAvailable() {
-        assertNotNull(Graal.getRuntime());
-        System.out.println(Graal.getRuntime().getClass());
-    }
-
-    @Test
-    public void testRuntimeNamed() {
-        assertNotNull(Graal.getRuntime().getName());
-        System.out.println(Graal.getRuntime().getName());
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java	Mon Feb 11 10:41:29 2013 +0100
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013, 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.asm.amd64.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.asm.test.*;
+
+public class SimpleAssemblerTest extends AssemblerTest {
+
+    @Test
+    public void intTest() {
+        CodeGenTest test = new CodeGenTest() {
+
+            @Override
+            public Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig) {
+                AMD64Assembler asm = new AMD64Assembler(target, registerConfig);
+                Register ret = registerConfig.getReturnRegister(Kind.Int);
+                asm.movl(ret, 8472);
+                asm.ret(0);
+                return asm.codeBuffer;
+            }
+        };
+        assertReturn("intStub", test, 8472);
+    }
+
+    @Test
+    public void doubleTest() {
+        CodeGenTest test = new CodeGenTest() {
+
+            @Override
+            public Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig) {
+                AMD64MacroAssembler asm = new AMD64MacroAssembler(target, registerConfig);
+                Register ret = registerConfig.getReturnRegister(Kind.Double);
+                compResult.recordDataReference(asm.codeBuffer.position(), Constant.forDouble(84.72), 8, false);
+                asm.movdbl(ret, Address.Placeholder);
+                asm.ret(0);
+                return asm.codeBuffer;
+            }
+        };
+        assertReturn("doubleStub", test, 84.72);
+    }
+
+    public static int intStub() {
+        return 0;
+    }
+
+    public static double doubleStub() {
+        return 0.0;
+    }
+}
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64AsmOptions.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64AsmOptions.java	Mon Feb 11 10:41:29 2013 +0100
@@ -27,7 +27,7 @@
     public static int Atomics = 0;
     public static boolean UseNormalNop = false;
     public static boolean UseAddressNop = true;
-    public static boolean UseIncDec = false;
+    public static boolean UseIncDec = true;
     public static boolean UseXmmLoadAndClearUpper = true;
-    public static boolean UseXmmRegToRegMoveAll = false;
+    public static boolean UseXmmRegToRegMoveAll = true;
 }
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Mon Feb 11 10:41:29 2013 +0100
@@ -2863,6 +2863,12 @@
         emitArith(0x85, 0xC0, dst, src);
     }
 
+    public final void testq(Register dst, Address src) {
+        prefixq(src, dst);
+        emitByte(0x85);
+        emitOperandHelper(dst, src);
+    }
+
     public final void xaddq(Address dst, Register src) {
         prefixq(dst, src);
         emitByte(0x0F);
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/X86InstructionDecoder.java	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,506 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.asm.amd64;
-
-public final class X86InstructionDecoder {
-
-    private boolean targetIs64Bit;
-    private byte[] code;
-    private int currentEndOfInstruction;
-    private int currentDisplacementPosition;
-
-    private static class Prefix {
-
-        // segment overrides
-        public static final int CSSegment = 0x2e;
-        public static final int SSSegment = 0x36;
-        public static final int DSSegment = 0x3e;
-        public static final int ESSegment = 0x26;
-        public static final int FSSegment = 0x64;
-        public static final int GSSegment = 0x65;
-        public static final int REX = 0x40;
-        public static final int REXB = 0x41;
-        public static final int REXX = 0x42;
-        public static final int REXXB = 0x43;
-        public static final int REXR = 0x44;
-        public static final int REXRB = 0x45;
-        public static final int REXRX = 0x46;
-        public static final int REXRXB = 0x47;
-        public static final int REXW = 0x48;
-        public static final int REXWB = 0x49;
-        public static final int REXWX = 0x4A;
-        public static final int REXWXB = 0x4B;
-        public static final int REXWR = 0x4C;
-        public static final int REXWRB = 0x4D;
-        public static final int REXWRX = 0x4E;
-        public static final int REXWRXB = 0x4F;
-    }
-
-    private X86InstructionDecoder(byte[] code, boolean targetIs64Bit) {
-        this.code = code;
-        this.targetIs64Bit = targetIs64Bit;
-    }
-
-    public int currentEndOfInstruction() {
-        return currentEndOfInstruction;
-    }
-
-    public int currentDisplacementPosition() {
-        return currentDisplacementPosition;
-    }
-
-    public void decodePosition(int inst) {
-
-        assert inst >= 0 && inst < code.length;
-
-        // Decode the given instruction, and return the Pointer of
-        // an embedded 32-bit operand word.
-
-        // If "which" is WhichOperand.disp32operand, selects the displacement portion
-        // of an effective Pointer specifier.
-        // If "which" is imm64Operand, selects the trailing immediate constant.
-        // If "which" is WhichOperand.call32operand, selects the displacement of a call or jump.
-        // Caller is responsible for ensuring that there is such an operand,
-        // and that it is 32/64 bits wide.
-
-        // If "which" is endPcOperand, find the end of the instruction.
-
-        int ip = inst;
-        boolean is64bit = false;
-
-        boolean hasDisp32 = false;
-        int tailSize = 0; // other random bytes (#32, #16, etc.) at end of insn
-
-        boolean againAfterPrefix = true;
-
-        while (againAfterPrefix) {
-            againAfterPrefix = false;
-            switch (0xFF & code[ip++]) {
-
-            // These convenience macros generate groups of "case" labels for the switch.
-
-                case Prefix.CSSegment:
-                case Prefix.SSSegment:
-                case Prefix.DSSegment:
-                case Prefix.ESSegment:
-                case Prefix.FSSegment:
-                case Prefix.GSSegment:
-                    // Seems dubious
-                    assert !targetIs64Bit : "shouldn't have that prefix";
-                    assert ip == inst + 1 : "only one prefix allowed";
-                    againAfterPrefix = true;
-                    break;
-
-                case 0x67:
-                case Prefix.REX:
-                case Prefix.REXB:
-                case Prefix.REXX:
-                case Prefix.REXXB:
-                case Prefix.REXR:
-                case Prefix.REXRB:
-                case Prefix.REXRX:
-                case Prefix.REXRXB:
-                    assert targetIs64Bit : "64bit prefixes";
-                    againAfterPrefix = true;
-                    break;
-
-                case Prefix.REXW:
-                case Prefix.REXWB:
-                case Prefix.REXWX:
-                case Prefix.REXWXB:
-                case Prefix.REXWR:
-                case Prefix.REXWRB:
-                case Prefix.REXWRX:
-                case Prefix.REXWRXB:
-                    assert targetIs64Bit : "64bit prefixes";
-                    is64bit = true;
-                    againAfterPrefix = true;
-                    break;
-
-                case 0xFF: // pushq a; decl a; incl a; call a; jmp a
-                case 0x88: // movb a, r
-                case 0x89: // movl a, r
-                case 0x8A: // movb r, a
-                case 0x8B: // movl r, a
-                case 0x8F: // popl a
-                    hasDisp32 = true;
-                    break;
-
-                case 0x68: // pushq #32
-                    currentEndOfInstruction = ip + 4;
-                    currentDisplacementPosition = ip;
-                    return; // not produced by emitOperand
-
-                case 0x66: // movw ... (size prefix)
-                    boolean againAfterSizePrefix2 = true;
-                    while (againAfterSizePrefix2) {
-                        againAfterSizePrefix2 = false;
-                        switch (0xFF & code[ip++]) {
-                            case Prefix.REX:
-                            case Prefix.REXB:
-                            case Prefix.REXX:
-                            case Prefix.REXXB:
-                            case Prefix.REXR:
-                            case Prefix.REXRB:
-                            case Prefix.REXRX:
-                            case Prefix.REXRXB:
-                            case Prefix.REXW:
-                            case Prefix.REXWB:
-                            case Prefix.REXWX:
-                            case Prefix.REXWXB:
-                            case Prefix.REXWR:
-                            case Prefix.REXWRB:
-                            case Prefix.REXWRX:
-                            case Prefix.REXWRXB:
-                                assert targetIs64Bit : "64bit prefix found";
-                                againAfterSizePrefix2 = true;
-                                break;
-                            case 0x8B: // movw r, a
-                            case 0x89: // movw a, r
-                                hasDisp32 = true;
-                                break;
-                            case 0xC7: // movw a, #16
-                                hasDisp32 = true;
-                                tailSize = 2; // the imm16
-                                break;
-                            case 0x0F: // several SSE/SSE2 variants
-                                ip--; // reparse the 0x0F
-                                againAfterPrefix = true;
-                                break;
-                            default:
-                                throw new InternalError("should not reach here");
-                        }
-                    }
-                    break;
-
-                case 0xB8: // movl/q r, #32/#64(oop?)
-                case 0xB9:
-                case 0xBA:
-                case 0xBB:
-                case 0xBC:
-                case 0xBD:
-                case 0xBE:
-                case 0xBF:
-                    currentEndOfInstruction = ip + (is64bit ? 8 : 4);
-                    currentDisplacementPosition = ip;
-                    return;
-
-                case 0x69: // imul r, a, #32
-                case 0xC7: // movl a, #32(oop?)
-                    tailSize = 4;
-                    hasDisp32 = true; // has both kinds of operands!
-                    break;
-
-                case 0x0F: // movx..., etc.
-                    switch (0xFF & code[ip++]) {
-                        case 0x12: // movlps
-                        case 0x28: // movaps
-                        case 0x2E: // ucomiss
-                        case 0x2F: // comiss
-                        case 0x54: // andps
-                        case 0x55: // andnps
-                        case 0x56: // orps
-                        case 0x57: // xorps
-                        case 0x6E: // movd
-                        case 0x7E: // movd
-                        case 0xAE: // ldmxcsr a
-                            // 64bit side says it these have both operands but that doesn't
-                            // appear to be true
-                            hasDisp32 = true;
-                            break;
-
-                        case 0xAD: // shrd r, a, %cl
-                        case 0xAF: // imul r, a
-                        case 0xBE: // movsbl r, a (movsxb)
-                        case 0xBF: // movswl r, a (movsxw)
-                        case 0xB6: // movzbl r, a (movzxb)
-                        case 0xB7: // movzwl r, a (movzxw)
-                        case 0x40: // cmovl cc, r, a
-                        case 0x41:
-                        case 0x42:
-                        case 0x43:
-                        case 0x44:
-                        case 0x45:
-                        case 0x46:
-                        case 0x47:
-                        case 0x48:
-                        case 0x49:
-                        case 0x4A:
-                        case 0x4B:
-                        case 0x4C:
-                        case 0x4D:
-                        case 0x4E:
-                        case 0x4F:
-                        case 0xB0: // cmpxchgb
-                        case 0xB1: // cmpxchg
-                        case 0xC1: // xaddl
-                        case 0xC7: // cmpxchg8
-                        case 0x90: // setcc a
-                        case 0x91:
-                        case 0x92:
-                        case 0x93:
-                        case 0x94:
-                        case 0x95:
-                        case 0x96:
-                        case 0x97:
-                        case 0x98:
-                        case 0x99:
-                        case 0x9A:
-                        case 0x9B:
-                        case 0x9C:
-                        case 0x9D:
-                        case 0x9E:
-                        case 0x9F:
-                            hasDisp32 = true;
-                            // fall out of the switch to decode the Pointer
-                            break;
-
-                        case 0xAC: // shrd r, a, #8
-                            hasDisp32 = true;
-                            tailSize = 1; // the imm8
-                            break;
-
-                        case 0x80: // jcc rdisp32
-                        case 0x81:
-                        case 0x82:
-                        case 0x83:
-                        case 0x84:
-                        case 0x85:
-                        case 0x86:
-                        case 0x87:
-                        case 0x88:
-                        case 0x89:
-                        case 0x8A:
-                        case 0x8B:
-                        case 0x8C:
-                        case 0x8D:
-                        case 0x8E:
-                        case 0x8F:
-                            currentEndOfInstruction = ip + 4;
-                            currentDisplacementPosition = ip;
-                            return;
-                        default:
-                            throw new InternalError("should not reach here");
-                    }
-                    break;
-
-                case 0x81: // addl a, #32; addl r, #32
-                    // also: orl, adcl, sbbl, andl, subl, xorl, cmpl
-                    // on 32bit in the case of cmpl, the imm might be an oop
-                    tailSize = 4;
-                    hasDisp32 = true; // has both kinds of operands!
-                    break;
-
-                case 0x83: // addl a, #8; addl r, #8
-                    // also: orl, adcl, sbbl, andl, subl, xorl, cmpl
-                    hasDisp32 = true; // has both kinds of operands!
-                    tailSize = 1;
-                    break;
-
-                case 0x9B:
-                    switch (0xFF & code[ip++]) {
-                        case 0xD9: // fnstcw a
-                            hasDisp32 = true;
-                            break;
-                        default:
-                            throw new InternalError("should not reach here");
-                    }
-                    break;
-
-                case 0x00: // addb a, r; addl a, r; addb r, a; addl r, a
-                case 0x01:
-                case 0x02:
-                case 0x03:
-                case 0x10: // adc...
-                case 0x11:
-                case 0x12:
-                case 0x13:
-                case 0x20: // and...
-                case 0x21:
-                case 0x22:
-                case 0x23:
-                case 0x30: // xor...
-                case 0x31:
-                case 0x32:
-                case 0x33:
-                case 0x08: // or...
-                case 0x09:
-                case 0x0a:
-                case 0x0b:
-                case 0x18: // sbb...
-                case 0x19:
-                case 0x1a:
-                case 0x1b:
-                case 0x28: // sub...
-                case 0x29:
-                case 0x2a:
-                case 0x2b:
-                case 0xF7: // mull a
-                case 0x8D: // lea r, a
-                case 0x87: // xchg r, a
-                case 0x38: // cmp...
-                case 0x39:
-                case 0x3a:
-                case 0x3b:
-                case 0x85: // test r, a
-                    hasDisp32 = true; // has both kinds of operands!
-                    break;
-
-                case 0xC1: // sal a, #8; sar a, #8; shl a, #8; shr a, #8
-                case 0xC6: // movb a, #8
-                case 0x80: // cmpb a, #8
-                case 0x6B: // imul r, a, #8
-                    hasDisp32 = true; // has both kinds of operands!
-                    tailSize = 1; // the imm8
-                    break;
-
-                case 0xE8: // call rdisp32
-                case 0xE9: // jmp rdisp32
-                    currentEndOfInstruction = ip + 4;
-                    currentDisplacementPosition = ip;
-                    return;
-
-                case 0xD1: // sal a, 1; sar a, 1; shl a, 1; shr a, 1
-                case 0xD3: // sal a, %cl; sar a, %cl; shl a, %cl; shr a, %cl
-                case 0xD9: // fldS a; fstS a; fstpS a; fldcw a
-                case 0xDD: // fldD a; fstD a; fstpD a
-                case 0xDB: // fildS a; fistpS a; fldX a; fstpX a
-                case 0xDF: // fildD a; fistpD a
-                case 0xD8: // faddS a; fsubrS a; fmulS a; fdivrS a; fcompS a
-                case 0xDC: // faddD a; fsubrD a; fmulD a; fdivrD a; fcompD a
-                case 0xDE: // faddpD a; fsubrpD a; fmulpD a; fdivrpD a; fcomppD a
-                    hasDisp32 = true;
-                    break;
-
-                case 0xF0: // Lock
-                    againAfterPrefix = true;
-                    break;
-
-                case 0xF3: // For SSE
-                case 0xF2: // For SSE2
-                    switch (0xFF & code[ip++]) {
-                        case Prefix.REX:
-                        case Prefix.REXB:
-                        case Prefix.REXX:
-                        case Prefix.REXXB:
-                        case Prefix.REXR:
-                        case Prefix.REXRB:
-                        case Prefix.REXRX:
-                        case Prefix.REXRXB:
-                        case Prefix.REXW:
-                        case Prefix.REXWB:
-                        case Prefix.REXWX:
-                        case Prefix.REXWXB:
-                        case Prefix.REXWR:
-                        case Prefix.REXWRB:
-                        case Prefix.REXWRX:
-                        case Prefix.REXWRXB:
-                            assert targetIs64Bit : "found 64bit prefix";
-                            ip++;
-                            // fall through
-                        default:
-                            ip++;
-                    }
-                    hasDisp32 = true; // has both kinds of operands!
-                    break;
-
-                default:
-                    throw new InternalError("should not reach here");
-            }
-        }
-
-        assert hasDisp32 : "(thomaswue) not sure if this holds: instruction has no disp32 field";
-
-        // parse the output of emitOperand
-        int op2 = 0xFF & code[ip++];
-        int base = op2 & 0x07;
-        int op3 = -1;
-        int b100 = 4;
-        int b101 = 5;
-        if (base == b100 && (op2 >> 6) != 3) {
-            op3 = 0xFF & code[ip++];
-            base = op3 & 0x07; // refetch the base
-        }
-        // now ip points at the disp (if any)
-
-        switch (op2 >> 6) {
-            case 0:
-                // [00 reg 100][ss index base]
-                // [00 reg 100][00 100 esp]
-                // [00 reg base]
-                // [00 reg 100][ss index 101][disp32]
-                // [00 reg 101] [disp32]
-
-                if (base == b101) {
-
-                    currentDisplacementPosition = ip;
-                    ip += 4; // skip the disp32
-                }
-                break;
-
-            case 1:
-                // [01 reg 100][ss index base][disp8]
-                // [01 reg 100][00 100 esp][disp8]
-                // [01 reg base] [disp8]
-                ip += 1; // skip the disp8
-                break;
-
-            case 2:
-                // [10 reg 100][ss index base][disp32]
-                // [10 reg 100][00 100 esp][disp32]
-                // [10 reg base] [disp32]
-                currentDisplacementPosition = ip;
-                ip += 4; // skip the disp32
-                break;
-
-            case 3:
-                // [11 reg base] (not a memory addressing mode)
-                break;
-        }
-
-        currentEndOfInstruction = ip + tailSize;
-    }
-
-    public static void patchRelativeInstruction(byte[] code, int codePos, int relative) {
-        X86InstructionDecoder decoder = new X86InstructionDecoder(code, true);
-        decoder.decodePosition(codePos);
-        int patchPos = decoder.currentDisplacementPosition();
-        int endOfInstruction = decoder.currentEndOfInstruction();
-        int offset = relative - endOfInstruction + codePos;
-        patchDisp32(code, patchPos, offset);
-    }
-
-    private static void patchDisp32(byte[] code, int pos, int offset) {
-        assert pos + 4 <= code.length;
-
-        assert code[pos] == 0;
-        assert code[pos + 1] == 0;
-        assert code[pos + 2] == 0;
-        assert code[pos + 3] == 0;
-
-        code[pos] = (byte) (offset & 0xFF);
-        code[pos + 1] = (byte) ((offset >> 8) & 0xFF);
-        code[pos + 2] = (byte) ((offset >> 16) & 0xFF);
-        code[pos + 3] = (byte) ((offset >> 24) & 0xFF);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Feb 11 10:41:29 2013 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2009, 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.asm.sparc;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.sparc.*;
+
+/**
+ * This class implements an assembler that can encode most SPARC instructions.
+ */
+public class SPARCAssembler extends AbstractAssembler {
+
+    @SuppressWarnings("unused")
+    public SPARCAssembler(TargetDescription target) {
+        super(target);
+        // TODO Auto-generated constructor stub
+        SPARC sparc;
+    }
+
+    @Override
+    public void align(int modulus) {
+        // SPARC: Implement alignment.
+    }
+
+    @Override
+    public void jmp(Label l) {
+        // SPARC: Implement jump.
+    }
+
+    @Override
+    protected void patchJumpTarget(int branch, int jumpTarget) {
+        // SPARC: Implement patching of jump target.
+    }
+
+    @Override
+    public void bangStack(int disp) {
+        // SPARC: Implement stack banging.
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Mon Feb 11 10:41:29 2013 +0100
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013, 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.asm.test;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.test.*;
+
+public abstract class AssemblerTest extends GraalTest {
+
+    protected final CodeCacheProvider codeCache;
+
+    public interface CodeGenTest {
+
+        Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig);
+    }
+
+    public AssemblerTest() {
+        this.codeCache = Graal.getRequiredCapability(CodeCacheProvider.class);
+    }
+
+    protected InstalledCode assembleMethod(Method m, CodeGenTest test) {
+        ResolvedJavaMethod method = codeCache.lookupJavaMethod(m);
+        RegisterConfig registerConfig = codeCache.lookupRegisterConfig(method);
+
+        CompilationResult compResult = new CompilationResult();
+
+        Buffer codeBuffer = test.generateCode(compResult, codeCache.getTarget(), registerConfig);
+        compResult.setTargetCode(codeBuffer.close(true), codeBuffer.position());
+
+        return codeCache.addMethod(method, compResult, null);
+    }
+
+    protected void assertReturn(String methodName, CodeGenTest test, Object expected, Object... args) {
+        Method method = getMethod(methodName);
+        InstalledCode code = assembleMethod(method, test);
+
+        Object actual = code.executeVarargs(args);
+        Assert.assertEquals("unexpected return value: " + actual, actual, expected);
+    }
+}
--- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java	Mon Feb 11 10:41:29 2013 +0100
@@ -22,8 +22,9 @@
  */
 package com.oracle.graal.asm;
 
+import java.nio.*;
+
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.Architecture.*;
 
 /**
  * The platform-independent base class for the assembler.
@@ -36,7 +37,7 @@
     public AbstractAssembler(TargetDescription target) {
         this.target = target;
 
-        if (target.arch.getByteOrder() == ByteOrder.BigEndian) {
+        if (target.arch.getByteOrder() == ByteOrder.BIG_ENDIAN) {
             this.codeBuffer = new Buffer.BigEndian();
         } else {
             this.codeBuffer = new Buffer.LittleEndian();
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Feb 11 10:41:29 2013 +0100
@@ -229,7 +229,7 @@
     }
 
     @Override
-    public void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) {
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) {
         boolean mirrored = emitCompare(left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
         switch (left.getKind().getStackKind()) {
@@ -248,7 +248,13 @@
     }
 
     @Override
-    public Variable emitCMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
+    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info) {
+        emitIntegerTest(left, right);
+        append(new BranchOp(negated ? Condition.NE : Condition.EQ, label, info));
+    }
+
+    @Override
+    public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
         boolean mirrored = emitCompare(left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
 
@@ -263,11 +269,29 @@
             case Double:
                 append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue)));
                 break;
-
+            default:
+                throw GraalInternalError.shouldNotReachHere("" + left.getKind());
         }
         return result;
     }
 
+    @Override
+    public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) {
+        emitIntegerTest(left, right);
+        Variable result = newVariable(trueValue.getKind());
+        append(new CondMoveOp(result, Condition.EQ, load(trueValue), loadNonConst(falseValue)));
+        return result;
+    }
+
+    private void emitIntegerTest(Value a, Value b) {
+        assert a.getKind().getStackKind() == Kind.Int || a.getKind() == Kind.Long;
+        if (LIRValueUtil.isVariable(b)) {
+            append(new AMD64TestOp(load(b), loadNonConst(a)));
+        } else {
+            append(new AMD64TestOp(load(a), loadNonConst(b)));
+        }
+    }
+
     /**
      * This method emits the compare instruction, and may reorder the operands. It returns true if
      * it did so.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Feb 11 10:41:29 2013 +0100
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.graal.compiler.sparc;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.calc.ConvertNode.Op;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+
+/**
+ * This class implements the SPARC specific portion of the LIR generator.
+ */
+public class SPARCLIRGenerator extends LIRGenerator {
+
+    public SPARCLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
+        super(graph, runtime, target, frameMap, method, lir);
+        // SPARC: Implement lir generator.
+    }
+
+    @Override
+    public Variable emitMove(Value input) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    protected boolean peephole(ValueNode valueNode) {
+        // SPARC: Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    protected void emitReturn(Value input) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    protected void emitNullCheckGuard(ValueNode object) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitJump(LabelRef label, LIRFrameState info) {
+        @SuppressWarnings("unused")
+        SPARCLIRInstruction instruction = null;
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public Variable emitConditionalMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    protected void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitBitCount(Variable result, Value operand) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitBitScanForward(Variable result, Value operand) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitBitScanReverse(Variable result, Value operand) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitMathAbs(Variable result, Variable input) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitMathSqrt(Variable result, Variable input) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitMathLog(Variable result, Variable input, boolean base10) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitMathCos(Variable result, Variable input) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitMathSin(Variable result, Variable input) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitMathTan(Variable result, Variable input) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitByteSwap(Variable result, Value operand) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean canInlineConstant(Constant c) {
+        // SPARC: Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean canStoreConstant(Constant c) {
+        // SPARC: Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public Address makeAddress(LocationNode location, ValueNode object) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void emitMove(Value src, Value dst) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public Value emitLoad(Value loadAddress, boolean canTrap) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void emitStore(Value storeAddress, Value input, boolean canTrap) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public Value emitLea(Value address) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitNegate(Value input) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitAdd(Value a, Value b) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitSub(Value a, Value b) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitMul(Value a, Value b) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitDiv(Value a, Value b) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitRem(Value a, Value b) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitUDiv(Value a, Value b) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitURem(Value a, Value b) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitAnd(Value a, Value b) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitOr(Value a, Value b) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitXor(Value a, Value b) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitShl(Value a, Value b) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitShr(Value a, Value b) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitUShr(Value a, Value b) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitConvert(Op opcode, Value inputVal) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void emitMembar(int barriers) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void visitCompareAndSwap(CompareAndSwapNode i) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void visitExceptionObject(ExceptionObjectNode i) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void visitSafepointNode(SafepointNode i) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void visitBreakpointNode(BreakpointNode i) {
+        // SPARC: Auto-generated method stub
+
+    }
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Mon Feb 11 10:41:29 2013 +0100
@@ -22,14 +22,29 @@
  */
 package com.oracle.graal.compiler.test;
 
+import static org.junit.Assert.*;
+
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.phases.common.*;
 
 public class CompareCanonicalizerTest extends GraalCompilerTest {
 
+    private StructuredGraph getCanonicalizedGraph(String name) {
+        StructuredGraph graph = parse(name);
+        new CanonicalizerPhase(null, runtime(), null).apply(graph);
+        return graph;
+    }
+
+    private static ValueNode getResult(StructuredGraph graph) {
+        assertTrue(graph.start().next() instanceof ReturnNode);
+        ReturnNode ret = (ReturnNode) graph.start().next();
+        return ret.result();
+    }
+
     @Test
     public void testCanonicalComparison() {
         StructuredGraph referenceGraph = parse("referenceCanonicalComparison");
@@ -40,8 +55,7 @@
         Assumptions assumptions = new Assumptions(false);
         new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph);
         for (int i = 1; i < 4; i++) {
-            StructuredGraph graph = parse("canonicalCompare" + i);
-            new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+            StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i);
             assertEquals(referenceGraph, graph);
         }
     }
@@ -77,4 +91,78 @@
             return 1;
         }
     }
+
+    @Test
+    public void testIntegerTest() {
+        for (int i = 1; i <= 4; i++) {
+            StructuredGraph graph = getCanonicalizedGraph("integerTest" + i);
+
+            ValueNode result = getResult(graph);
+            assertTrue(result instanceof ConditionalNode);
+            ConditionalNode mat = (ConditionalNode) result;
+            assertTrue(mat.condition() instanceof IntegerTestNode);
+            IntegerTestNode test = (IntegerTestNode) mat.condition();
+            LocalNode local0 = graph.getLocal(0);
+            LocalNode local1 = graph.getLocal(1);
+            assertTrue((test.x() == local0 && test.y() == local1) || (test.x() == local1 && test.y() == local0));
+        }
+    }
+
+    public static boolean integerTest1(int x, int y) {
+        return (x & y) == 0;
+    }
+
+    public static boolean integerTest2(long x, long y) {
+        return 0 == (x & y);
+    }
+
+    public static boolean integerTest3(long x, long y) {
+        int c = 5;
+        return (c - 5) == (x & y);
+    }
+
+    public static boolean integerTest4(int x, int y) {
+        int c = 10;
+        return (x & y) == (10 - c);
+    }
+
+    @Test
+    public void testIntegerTestCanonicalization() {
+        ValueNode result = getResult(getCanonicalizedGraph("integerTestCanonicalization1"));
+        assertTrue(result.isConstant() && result.asConstant().asLong() == 1);
+        result = getResult(getCanonicalizedGraph("integerTestCanonicalization2"));
+        assertTrue(result.isConstant() && result.asConstant().asLong() == 1);
+        result = getResult(getCanonicalizedGraph("integerTestCanonicalization3"));
+        assertTrue(result instanceof ConditionalNode);
+    }
+
+    public static int integerTestCanonicalization1(boolean b) {
+        int x = b ? 128 : 256;
+        if ((x & 8) == 0) {
+            return 1;
+        } else {
+            return 2;
+        }
+    }
+
+    public static int integerTestCanonicalization2(boolean b) {
+        int x = b ? 128 : 256;
+        int y = b ? 32 : 64;
+        if ((x & y) == 0) {
+            return 1;
+        } else {
+            return 2;
+        }
+    }
+
+    public static int integerTestCanonicalization3(boolean b) {
+        int x = b ? 128 : 64;
+        int y = b ? 32 : 64;
+        if ((x & y) == 0) {
+            return 1;
+        } else {
+            return 2;
+        }
+    }
+
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Feb 11 10:41:29 2013 +0100
@@ -43,6 +43,7 @@
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.printer.*;
+import com.oracle.graal.test.*;
 
 /**
  * Base class for Graal compiler unit tests.
@@ -63,7 +64,7 @@
  * <p>
  * These tests will be run by the {@code mx unittest} command.
  */
-public abstract class GraalCompilerTest {
+public abstract class GraalCompilerTest extends GraalTest {
 
     protected final GraalCodeCacheProvider runtime;
     protected final GraalCompiler graalCompiler;
@@ -146,21 +147,6 @@
         return parse(getMethod(methodName));
     }
 
-    protected Method getMethod(String methodName) {
-        Method found = null;
-        for (Method m : this.getClass().getMethods()) {
-            if (m.getName().equals(methodName)) {
-                Assert.assertNull(found);
-                found = m;
-            }
-        }
-        if (found != null) {
-            return found;
-        } else {
-            throw new RuntimeException("method not found: " + methodName);
-        }
-    }
-
     private static int compilationId = 0;
 
     /**
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Mon Feb 11 10:41:29 2013 +0100
@@ -168,7 +168,7 @@
         // TypeSystemTest.outputGraph(graph);
         Assumptions assumptions = new Assumptions(false);
         new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
-        new ConditionalEliminationPhase().apply(graph);
+        new ConditionalEliminationPhase(runtime()).apply(graph);
         new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
         StructuredGraph referenceGraph = parse(referenceSnippet);
         assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Mon Feb 11 10:41:29 2013 +0100
@@ -127,10 +127,7 @@
             }
         } else {
             if (a == constantObject2 || a == constantObject3) {
-                if (a != null) {
-                    return 11;
-                }
-                return 2;
+                return 11;
             }
         }
         if (a == constantObject1) {
@@ -185,34 +182,25 @@
         return ((InputStream) o).available();
     }
 
-    @SuppressWarnings("unused")
     private void test(String snippet, String referenceSnippet) {
-        // TODO(ls) temporarily disabled, reintroduce when a proper type system is available
-        if (false) {
-            StructuredGraph graph = parse(snippet);
-            Debug.dump(graph, "Graph");
-            Assumptions assumptions = new Assumptions(false);
-            new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
-            new ConditionalEliminationPhase().apply(graph);
-            new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
-            new GlobalValueNumberingPhase().apply(graph);
-            StructuredGraph referenceGraph = parse(referenceSnippet);
-            new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph);
-            new GlobalValueNumberingPhase().apply(referenceGraph);
-            assertEquals(referenceGraph, graph);
-        }
+        StructuredGraph graph = parse(snippet);
+        Debug.dump(graph, "Graph");
+        Assumptions assumptions = new Assumptions(false);
+        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+        new ConditionalEliminationPhase(runtime()).apply(graph);
+        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+        // a second canonicalizer is needed to process nested MaterializeNodes
+        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+        StructuredGraph referenceGraph = parse(referenceSnippet);
+        new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph);
+        assertEquals(referenceGraph, graph);
     }
 
     @Override
     protected void assertEquals(StructuredGraph expected, StructuredGraph graph) {
         if (expected.getNodeCount() != graph.getNodeCount()) {
-            // Debug.dump(expected, "Node count not matching - expected");
-            // Debug.dump(graph, "Node count not matching - actual");
-            // System.out.println("================ expected");
-            // outputGraph(expected);
-            // System.out.println("================ actual");
-            // outputGraph(graph);
-            // new IdealGraphPrinterDumpHandler().dump(graph, "asdf");
+            outputGraph(expected, "expected");
+            outputGraph(graph, "actual");
             Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount());
         }
     }
@@ -250,18 +238,14 @@
         }
     }
 
-    @SuppressWarnings("unused")
     private <T extends Node & Node.IterableNodeType> void test(String snippet, Class<T> clazz) {
-        // TODO(ls) temporarily disabled, reintroduce when a proper type system is available
-        if (false) {
-            StructuredGraph graph = parse(snippet);
-            Debug.dump(graph, "Graph");
-            Assumptions assumptions = new Assumptions(false);
-            new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
-            new ConditionalEliminationPhase().apply(graph);
-            new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
-            Debug.dump(graph, "Graph");
-            Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext());
-        }
+        StructuredGraph graph = parse(snippet);
+        Debug.dump(graph, "Graph");
+        Assumptions assumptions = new Assumptions(false);
+        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+        new ConditionalEliminationPhase(runtime()).apply(graph);
+        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+        Debug.dump(graph, "Graph");
+        Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext());
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Feb 11 10:41:29 2013 +0100
@@ -30,6 +30,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
@@ -184,8 +185,8 @@
     public void testInstanceOf() {
         ReturnNode returnNode = testEscapeAnalysis("testInstanceOfSnippet", null, false);
         ValueNode result = returnNode.result();
-        Assert.assertTrue(result instanceof MaterializeNode);
-        Assert.assertEquals(Constant.TRUE, ((MaterializeNode) result).condition().asConstant());
+        Assert.assertTrue(result instanceof ConditionalNode);
+        Assert.assertEquals(Constant.TRUE, ((ConditionalNode) result).condition().asConstant());
     }
 
     public boolean testInstanceOfSnippet() {
@@ -198,7 +199,7 @@
         StructuredGraph graph = parse(snippet);
         try {
             for (Invoke n : graph.getInvokes()) {
-                n.node().setProbability(100000);
+                n.setInliningRelevance(1);
             }
 
             Assumptions assumptions = new Assumptions(false);
@@ -211,7 +212,7 @@
                 Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant());
                 Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant());
             }
-            int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewObjectArrayNode.class).count() + graph.getNodes(MaterializeObjectNode.class).count();
+            int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewArrayNode.class).count() + graph.getNodes(MaterializeObjectNode.class).count();
             Assert.assertEquals(0, newInstanceCount);
             return returnNode;
         } catch (AssertionFailedError t) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Mon Feb 11 10:41:29 2013 +0100
@@ -126,8 +126,7 @@
     final void testMaterialize(final String snippet, double expectedProbability, int expectedCount, Class<? extends Node>... invalidNodeClasses) {
         StructuredGraph result = processMethod(snippet);
         Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes(NewInstanceNode.class).isEmpty());
-        Assert.assertTrue("partial escape analysis should have removed all NewObjectArrayNode allocations", result.getNodes(NewObjectArrayNode.class).isEmpty());
-        Assert.assertTrue("partial escape analysis should have removed all NewPrimitiveArrayNode allocations", result.getNodes(NewPrimitiveArrayNode.class).isEmpty());
+        Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes(NewArrayNode.class).isEmpty());
         double probabilitySum = 0;
         int materializeCount = 0;
         for (MaterializeObjectNode materialize : result.getNodes(MaterializeObjectNode.class)) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Feb 11 10:41:29 2013 +0100
@@ -612,6 +612,8 @@
             emitCompareBranch((CompareNode) node, trueSuccessor, falseSuccessor, info);
         } else if (node instanceof ConstantNode) {
             emitConstantBranch(((ConstantNode) node).asConstant().asBoolean(), trueSuccessor, falseSuccessor, info);
+        } else if (node instanceof IntegerTestNode) {
+            emitIntegerTestBranch((IntegerTestNode) node, trueSuccessor, falseSuccessor, info);
         } else {
             throw GraalInternalError.unimplemented(node.toString());
         }
@@ -619,23 +621,34 @@
 
     private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
         if (falseSuccessor != null) {
-            emitBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.NE, false, falseSuccessor, info);
+            emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.NE, false, falseSuccessor, info);
             if (trueSuccessor != null) {
                 emitJump(trueSuccessor, null);
             }
         } else {
-            emitBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueSuccessor, info);
+            emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueSuccessor, info);
         }
     }
 
     public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) {
         if (falseSuccessorBlock != null) {
-            emitBranch(operand(compare.x()), operand(compare.y()), compare.condition().negate(), !compare.unorderedIsTrue(), falseSuccessorBlock, info);
+            emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition().negate(), !compare.unorderedIsTrue(), falseSuccessorBlock, info);
             if (trueSuccessorBlock != null) {
                 emitJump(trueSuccessorBlock, null);
             }
         } else {
-            emitBranch(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessorBlock, info);
+            emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessorBlock, info);
+        }
+    }
+
+    public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) {
+        if (falseSuccessorBlock != null) {
+            emitIntegerTestBranch(operand(test.x()), operand(test.y()), true, falseSuccessorBlock, info);
+            if (trueSuccessorBlock != null) {
+                emitJump(trueSuccessorBlock, null);
+            }
+        } else {
+            emitIntegerTestBranch(operand(test.x()), operand(test.y()), false, trueSuccessorBlock, info);
         }
     }
 
@@ -655,33 +668,31 @@
 
     public Variable emitConditional(BooleanNode node, Value trueValue, Value falseValue) {
         if (node instanceof IsNullNode) {
-            return emitNullCheckConditional((IsNullNode) node, trueValue, falseValue);
+            IsNullNode isNullNode = (IsNullNode) node;
+            return emitConditionalMove(operand(isNullNode.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueValue, falseValue);
         } else if (node instanceof CompareNode) {
-            return emitCompareConditional((CompareNode) node, trueValue, falseValue);
+            CompareNode compare = (CompareNode) node;
+            return emitConditionalMove(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue);
         } else if (node instanceof ConstantNode) {
-            return emitConstantConditional(((ConstantNode) node).asConstant().asBoolean(), trueValue, falseValue);
+            ConstantNode constantNode = (ConstantNode) node;
+            return emitMove(constantNode.asConstant().asBoolean() ? trueValue : falseValue);
+        } else if (node instanceof IntegerTestNode) {
+            IntegerTestNode test = (IntegerTestNode) node;
+            return emitIntegerTestMove(operand(test.x()), operand(test.y()), trueValue, falseValue);
         } else {
             throw GraalInternalError.unimplemented(node.toString());
         }
     }
 
-    private Variable emitNullCheckConditional(IsNullNode node, Value trueValue, Value falseValue) {
-        return emitCMove(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueValue, falseValue);
-    }
-
-    private Variable emitConstantConditional(boolean value, Value trueValue, Value falseValue) {
-        return emitMove(value ? trueValue : falseValue);
-    }
-
-    private Variable emitCompareConditional(CompareNode compare, Value trueValue, Value falseValue) {
-        return emitCMove(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue);
-    }
-
     public abstract void emitJump(LabelRef label, LIRFrameState info);
 
-    public abstract void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info);
+    public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info);
+
+    public abstract void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info);
 
-    public abstract Variable emitCMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
+    public abstract Variable emitConditionalMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
+
+    public abstract Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue);
 
     @Override
     public void emitInvoke(Invoke x) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Mon Feb 11 10:41:29 2013 +0100
@@ -195,5 +195,4 @@
     protected RegisterConfig createRegisterConfig(boolean globalStubConfig) {
         return new AMD64HotSpotRegisterConfig(config, globalStubConfig);
     }
-
 }
--- a/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/CompilationServer.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/CompilationServer.java	Mon Feb 11 10:41:29 2013 +0100
@@ -62,7 +62,6 @@
      */
     public CompilationServer(boolean multiple) {
         this.multiple = multiple;
-        HotSpotOptions.setDefaultOptions();
     }
 
     public void addConnectionObserver(ConnectionObserver observer) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Mon Feb 11 10:41:29 2013 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.sparc;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.sparc.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * HotSpot SPARC specific backend.
+ */
+public class SPARCHotSpotBackend extends HotSpotBackend {
+
+    public SPARCHotSpotBackend(HotSpotRuntime runtime, TargetDescription target) {
+        super(runtime, target);
+    }
+
+    @Override
+    public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
+        return new SPARCLIRGenerator(graph, this.runtime(), this.target, frameMap, method, lir);
+    }
+
+    @Override
+    public TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir) {
+        // SPARC: Create assembler.
+        return null;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIR lir) {
+        // SPARC: Emit code
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java	Mon Feb 11 10:41:29 2013 +0100
@@ -0,0 +1,62 @@
+/*
+ * 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.sparc;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+
+/**
+ * SPARC specific implementation of {@link HotSpotGraalRuntime}.
+ */
+final class SPARCHotSpotGraalRuntime extends HotSpotGraalRuntime {
+
+    private SPARCHotSpotGraalRuntime() {
+    }
+
+    /**
+     * Called from C++ code to retrieve the singleton instance, creating it first if necessary.
+     */
+    public static HotSpotGraalRuntime makeInstance() {
+        if (getInstance() == null) {
+            setInstance(new SPARCHotSpotGraalRuntime());
+        }
+        return getInstance();
+    }
+
+    @Override
+    protected TargetDescription createTarget() {
+        // SPARC: Create target description.
+        return null;
+    }
+
+    @Override
+    protected HotSpotBackend createBackend() {
+        return new SPARCHotSpotBackend(getRuntime(), getTarget());
+    }
+
+    @Override
+    protected HotSpotRuntime createRuntime() {
+        return new SPARCHotSpotRuntime(config, this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRuntime.java	Mon Feb 11 10:41:29 2013 +0100
@@ -0,0 +1,53 @@
+/*
+ * 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.sparc;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+
+public class SPARCHotSpotRuntime extends HotSpotRuntime {
+
+    public SPARCHotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) {
+        super(config, graalRuntime);
+        // SPARC: Register stubs.
+    }
+
+    @Override
+    public Register threadRegister() {
+        // SPARC: Define thread register.
+        return null;
+    }
+
+    @Override
+    public Register stackPointerRegister() {
+        // SPARC: Define stack pointer register.
+        return null;
+    }
+
+    @Override
+    protected RegisterConfig createRegisterConfig(boolean globalStubConfig) {
+        // SPARC: Create register configuration.
+        return null;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Feb 11 10:41:29 2013 +0100
@@ -28,7 +28,6 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.interpreter.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.*;
@@ -259,15 +258,12 @@
     @SuppressWarnings("unchecked")
     @Override
     public <T> T getCapability(Class<T> clazz) {
-        if (clazz == GraalCodeCacheProvider.class || clazz == MetaAccessProvider.class || clazz == SnippetProvider.class) {
+        if (clazz == GraalCodeCacheProvider.class || clazz == CodeCacheProvider.class || clazz == MetaAccessProvider.class || clazz == SnippetProvider.class) {
             return (T) getRuntime();
         }
         if (clazz == GraalCompiler.class) {
             return (T) getCompiler();
         }
-        if (clazz == RuntimeInterpreterInterface.class) {
-            return (T) getRuntimeInterpreterInterface();
-        }
         return null;
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Mon Feb 11 10:41:29 2013 +0100
@@ -31,11 +31,6 @@
 
 public class HotSpotOptions {
 
-    public static void setDefaultOptions() {
-        GraalOptions.MethodEndBreakpointGuards = 2;
-        GraalOptions.ResolveClassBeforeStaticInvoke = false;
-    }
-
     // Called from VM code
     public static boolean setOption(String option) {
         if (option.length() == 0) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeInterpreterInterface.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeInterpreterInterface.java	Mon Feb 11 10:41:29 2013 +0100
@@ -28,11 +28,10 @@
 
 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 {
+public class HotSpotRuntimeInterpreterInterface {
 
     private final MetaAccessProvider metaProvider;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Mon Feb 11 10:41:29 2013 +0100
@@ -29,6 +29,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.snippets.*;
 
 /**
  * Represents a field in a HotSpot type.
@@ -86,10 +87,16 @@
             }
             return constant;
         } else {
+            /*
+             * for non-static final fields, we must assume that they are only initialized if they
+             * have a non-default value.
+             */
             assert !Modifier.isStatic(flags);
-            // TODO (chaeubl) HotSpot does not trust final non-static fields (see ciField.cpp)
             if (Modifier.isFinal(getModifiers())) {
-                return readValue(receiver);
+                Constant value = readValue(receiver);
+                if (assumeNonStaticFinalFieldsAsFinal(receiver.asObject().getClass()) || !value.isDefaultForKind()) {
+                    return value;
+                }
             }
         }
         return null;
@@ -113,6 +120,10 @@
         return clazz == GraalOptions.class;
     }
 
+    private static boolean assumeNonStaticFinalFieldsAsFinal(Class<?> clazz) {
+        return clazz == SnippetCounter.class;
+    }
+
     @Override
     public HotSpotResolvedObjectType getDeclaringClass() {
         return holder;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Feb 11 10:41:29 2013 +0100
@@ -943,4 +943,9 @@
                 throw GraalInternalError.shouldNotReachHere();
         }
     }
+
+    @Override
+    public TargetDescription getTarget() {
+        return graalRuntime.getTarget();
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Mon Feb 11 10:41:29 2013 +0100
@@ -79,7 +79,7 @@
             isNull.inc();
         } else {
             Word objectHub = loadHub(object);
-            if (objectHub != exactHub) {
+            if (objectHub.notEqual(exactHub)) {
                 probability(DEOPT_PATH_PROBABILITY);
                 exactMiss.inc();
                 //bkpt(object, exactHub, objectHub);
@@ -108,7 +108,7 @@
             isNull.inc();
         } else {
             Word objectHub = loadHub(object);
-            if (objectHub.readWord(superCheckOffset) != hub) {
+            if (objectHub.readWord(superCheckOffset).notEqual(hub)) {
                 probability(DEOPT_PATH_PROBABILITY);
                 displayMiss.inc();
                 DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException);
@@ -136,7 +136,7 @@
             ExplodeLoopNode.explodeLoop();
             for (int i = 0; i < hints.length; i++) {
                 Word hintHub = hints[i];
-                if (hintHub == objectHub) {
+                if (hintHub.equal(objectHub)) {
                     hintsHit.inc();
                     return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic());
                 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java	Mon Feb 11 10:41:29 2013 +0100
@@ -27,7 +27,7 @@
 
 import java.lang.reflect.*;
 
-import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution;
 import com.oracle.graal.word.*;
@@ -41,7 +41,7 @@
     @MethodSubstitution(isStatic = false)
     public static int getModifiers(final Class<?> thisObj) {
         Word klass = loadWordFromObject(thisObj, klassOffset());
-        if (klass == Word.zero()) {
+        if (klass.equal(0)) {
             // Class for primitive type
             return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC;
         } else {
@@ -52,7 +52,7 @@
     @MethodSubstitution(isStatic = false)
     public static boolean isInterface(final Class<?> thisObj) {
         Word klass = loadWordFromObject(thisObj, klassOffset());
-        if (klass == Word.zero()) {
+        if (klass.equal(0)) {
             return false;
         } else {
             int accessFlags = klass.readInt(klassAccessFlagsOffset());
@@ -63,7 +63,7 @@
     @MethodSubstitution(isStatic = false)
     public static boolean isArray(final Class<?> thisObj) {
         Word klass = loadWordFromObject(thisObj, klassOffset());
-        if (klass == Word.zero()) {
+        if (klass.equal(0)) {
             return false;
         } else {
             int layoutHelper = klass.readInt(klassLayoutHelperOffset());
@@ -74,13 +74,13 @@
     @MethodSubstitution(isStatic = false)
     public static boolean isPrimitive(final Class<?> thisObj) {
         Word klass = loadWordFromObject(thisObj, klassOffset());
-        return klass == Word.zero();
+        return klass.equal(0);
     }
 
     @MethodSubstitution(isStatic = false)
     public static Class<?> getSuperclass(final Class<?> thisObj) {
         Word klass = loadWordFromObject(thisObj, klassOffset());
-        if (klass != Word.zero()) {
+        if (klass.notEqual(0)) {
             int accessFlags = klass.readInt(klassAccessFlagsOffset());
             if ((accessFlags & Modifier.INTERFACE) == 0) {
                 int layoutHelper = klass.readInt(klassLayoutHelperOffset());
@@ -88,7 +88,7 @@
                     return Object.class;
                 } else {
                     Word superKlass = klass.readWord(klassSuperKlassOffset());
-                    if (superKlass == Word.zero()) {
+                    if (superKlass.equal(0)) {
                         return null;
                     } else {
                         return unsafeCast(superKlass.readObject(classMirrorOffset()), Class.class, true, true);
@@ -102,7 +102,7 @@
     @MethodSubstitution(isStatic = false)
     public static Class<?> getComponentType(final Class<?> thisObj) {
         Word klass = loadWordFromObject(thisObj, klassOffset());
-        if (klass != Word.zero()) {
+        if (klass.notEqual(0)) {
             int layoutHelper = klass.readInt(klassLayoutHelperOffset());
             if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) {
                 return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset()), Class.class, true, true);
@@ -113,6 +113,6 @@
 
     @MethodSubstitution(isStatic = false)
     public static boolean isInstance(final Class<?> thisObj, Object obj) {
-        return !thisObj.isPrimitive() && MaterializeNode.isInstance(thisObj, obj);
+        return !thisObj.isPrimitive() && ConditionalNode.materializeIsInstance(thisObj, obj);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Mon Feb 11 10:41:29 2013 +0100
@@ -458,7 +458,7 @@
 
         // this code is independent from biased locking (although it does not look that way)
         final Word biasedLock = mark.and(biasedLockMaskInPlace());
-        if (biasedLock == Word.unsigned(unlockedMask())) {
+        if (biasedLock.equal(Word.unsigned(unlockedMask()))) {
             probability(FAST_PATH_PROBABILITY);
             int hash = (int) mark.unsignedShiftRight(identityHashCodeShift()).rawValue();
             if (hash != uninitializedIdentityHashCodeValue()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java	Mon Feb 11 10:41:29 2013 +0100
@@ -73,7 +73,7 @@
             return falseValue;
         }
         Word objectHub = loadHub(object);
-        if (objectHub != exactHub) {
+        if (objectHub.notEqual(exactHub)) {
             probability(LIKELY_PROBABILITY);
             exactMiss.inc();
             return falseValue;
@@ -99,7 +99,7 @@
             return falseValue;
         }
         Word objectHub = loadHub(object);
-        if (objectHub.readWord(superCheckOffset) != hub) {
+        if (objectHub.readWord(superCheckOffset).notEqual(hub)) {
             probability(NOT_LIKELY_PROBABILITY);
             displayMiss.inc();
             return falseValue;
@@ -129,7 +129,7 @@
         ExplodeLoopNode.explodeLoop();
         for (int i = 0; i < hints.length; i++) {
             Word hintHub = hints[i];
-            if (hintHub == objectHub) {
+            if (hintHub.equal(objectHub)) {
                 probability(NOT_FREQUENT_PROBABILITY);
                 hintsHit.inc();
                 return trueValue;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java	Mon Feb 11 10:41:29 2013 +0100
@@ -76,10 +76,7 @@
     public static final boolean CHECK_BALANCED_MONITORS = Boolean.getBoolean("graal.monitors.checkBalanced");
 
     @Snippet
-    public static void monitorenter(@Parameter("object")
-    Object object, @ConstantParameter("checkNull")
-    boolean checkNull, @ConstantParameter("trace")
-    boolean trace) {
+    public static void monitorenter(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) {
         verifyOop(object);
 
         if (checkNull && object == null) {
@@ -105,7 +102,7 @@
             final Word biasableLockBits = mark.and(biasedLockMaskInPlace());
 
             // First check to see whether biasing is enabled for this object
-            if (biasableLockBits != Word.unsigned(biasedLockPattern())) {
+            if (biasableLockBits.notEqual(Word.unsigned(biasedLockPattern()))) {
                 // Biasing not enabled -> fall through to lightweight locking
             } else {
                 probability(FREQUENT_PROBABILITY);
@@ -118,7 +115,7 @@
                 trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord);
                 trace(trace, "           thread: 0x%016lx\n", thread);
                 trace(trace, "              tmp: 0x%016lx\n", tmp);
-                if (tmp == Word.zero()) {
+                if (tmp.equal(0)) {
                     // Object is already biased to current thread -> done
                     probability(FREQUENT_PROBABILITY);
                     traceObject(trace, "+lock{bias:existing}", object);
@@ -134,7 +131,7 @@
                 // If the low three bits in the xor result aren't clear, that means
                 // the prototype header is no longer biasable and we have to revoke
                 // the bias on this object.
-                if (tmp.and(biasedLockMaskInPlace()) == Word.zero()) {
+                if (tmp.and(biasedLockMaskInPlace()).equal(0)) {
                     probability(FREQUENT_PROBABILITY);
                     // Biasing is still enabled for object's type. See whether the
                     // epoch of the current bias is still valid, meaning that the epoch
@@ -145,7 +142,7 @@
                     // that the current epoch is invalid in order to do this because
                     // otherwise the manipulations it performs on the mark word are
                     // illegal.
-                    if (tmp.and(epochMaskInPlace()) == Word.zero()) {
+                    if (tmp.and(epochMaskInPlace()).equal(0)) {
                         probability(FREQUENT_PROBABILITY);
                         // The epoch of the current bias is still valid but we know nothing
                         // about the owner; it might be set or it might be clear. Try to
@@ -157,7 +154,7 @@
                         Word biasedMark = unbiasedMark.or(thread);
                         trace(trace, "     unbiasedMark: 0x%016lx\n", unbiasedMark);
                         trace(trace, "       biasedMark: 0x%016lx\n", biasedMark);
-                        if (compareAndSwap(object, markOffset(), unbiasedMark, biasedMark) == unbiasedMark) {
+                        if (compareAndSwap(object, markOffset(), unbiasedMark, biasedMark).equal(unbiasedMark)) {
                             // Object is now biased to current thread -> done
                             traceObject(trace, "+lock{bias:acquired}", object);
                             return;
@@ -178,7 +175,7 @@
                         // the bias from one thread to another directly in this situation.
                         Word biasedMark = prototypeMarkWord.or(thread);
                         trace(trace, "       biasedMark: 0x%016lx\n", biasedMark);
-                        if (compareAndSwap(object, markOffset(), mark, biasedMark) == mark) {
+                        if (compareAndSwap(object, markOffset(), mark, biasedMark).equal(mark)) {
                             // Object is now biased to current thread -> done
                             traceObject(trace, "+lock{bias:transfer}", object);
                             return;
@@ -223,7 +220,7 @@
         // Test if the object's mark word is unlocked, and if so, store the
         // (address of) the lock slot into the object's mark word.
         Word currentMark = compareAndSwap(object, markOffset(), unlockedMark, lock);
-        if (currentMark != unlockedMark) {
+        if (currentMark.notEqual(unlockedMark)) {
             trace(trace, "      currentMark: 0x%016lx\n", currentMark);
             // The mark word in the object header was not the same.
             // Either the object is locked by another thread or is already locked
@@ -242,7 +239,7 @@
             // significant 2 bits cleared and page_size is a power of 2
             final Word alignedMask = Word.unsigned(wordSize() - 1);
             final Word stackPointer = stackPointer();
-            if (currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())) != Word.zero()) {
+            if (currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0)) {
                 // Most likely not a recursive lock, go into a slow runtime call
                 probability(DEOPT_PATH_PROBABILITY);
                 traceObject(trace, "+lock{stub:failed-cas}", object);
@@ -268,10 +265,7 @@
      * Calls straight out to the monitorenter stub.
      */
     @Snippet
-    public static void monitorenterStub(@Parameter("object")
-    Object object, @ConstantParameter("checkNull")
-    boolean checkNull, @ConstantParameter("trace")
-    boolean trace) {
+    public static void monitorenterStub(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) {
         verifyOop(object);
         incCounter();
         if (checkNull && object == null) {
@@ -285,9 +279,7 @@
     }
 
     @Snippet
-    public static void monitorexit(@Parameter("object")
-    Object object, @ConstantParameter("trace")
-    boolean trace) {
+    public static void monitorexit(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) {
         trace(trace, "           object: 0x%016lx\n", Word.fromObject(object));
         if (useBiasedLocking()) {
             // Check for biased locking unlock case, which is a no-op
@@ -298,7 +290,7 @@
             // the bias bit would be clear.
             final Word mark = loadWordFromObject(object, markOffset());
             trace(trace, "             mark: 0x%016lx\n", mark);
-            if (mark.and(biasedLockMaskInPlace()) == Word.unsigned(biasedLockPattern())) {
+            if (mark.and(biasedLockMaskInPlace()).equal(Word.unsigned(biasedLockPattern()))) {
                 probability(FREQUENT_PROBABILITY);
                 endLockScope();
                 decCounter();
@@ -313,7 +305,7 @@
         final Word displacedMark = lock.readWord(lockDisplacedMarkOffset());
         trace(trace, "    displacedMark: 0x%016lx\n", displacedMark);
 
-        if (displacedMark == Word.zero()) {
+        if (displacedMark.equal(0)) {
             // Recursive locking => done
             traceObject(trace, "-lock{recursive}", object);
         } else {
@@ -321,7 +313,7 @@
             // Test if object's mark word is pointing to the displaced mark word, and if so, restore
             // the displaced mark in the object - if the object's mark word is not pointing to
             // the displaced mark word, do unlocking via runtime call.
-            if (DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark) != lock) {
+            if (DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark).notEqual(lock)) {
                 // The object's mark word was not pointing to the displaced header,
                 // we do unlocking via runtime call.
                 probability(DEOPT_PATH_PROBABILITY);
@@ -339,9 +331,7 @@
      * Calls straight out to the monitorexit stub.
      */
     @Snippet
-    public static void monitorexitStub(@Parameter("object")
-    Object object, @ConstantParameter("trace")
-    boolean trace) {
+    public static void monitorexitStub(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) {
         verifyOop(object);
         traceObject(trace, "-lock{stub}", object);
         MonitorExitStubCall.call(object);
@@ -434,8 +424,7 @@
             this.useFastLocking = useFastLocking;
         }
 
-        public void lower(MonitorEnterNode monitorenterNode, @SuppressWarnings("unused")
-        LoweringTool tool) {
+        public void lower(MonitorEnterNode monitorenterNode, @SuppressWarnings("unused") LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) monitorenterNode.graph();
 
             checkBalancedMonitors(graph);
@@ -466,8 +455,7 @@
             }
         }
 
-        public void lower(MonitorExitNode monitorexitNode, @SuppressWarnings("unused")
-        LoweringTool tool) {
+        public void lower(MonitorExitNode monitorexitNode, @SuppressWarnings("unused") LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) monitorexitNode.graph();
             FrameState stateAfter = monitorexitNode.stateAfter();
             boolean eliminated = monitorexitNode.eliminated();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Mon Feb 11 10:41:29 2013 +0100
@@ -84,7 +84,7 @@
                     @ConstantParameter("locked") boolean locked) {
 
         Object result;
-        if (memory == Word.zero()) {
+        if (memory.equal(0)) {
             new_stub.inc();
             result = NewInstanceStubCall.call(hub);
         } else {
@@ -118,7 +118,7 @@
 
     private static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, int headerSize, boolean fillContents) {
         Object result;
-        if (memory == Word.zero()) {
+        if (memory.equal(0)) {
             newarray_stub.inc();
             result = NewArrayStubCall.call(hub, length);
         } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/TypeCheckSnippetUtils.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/TypeCheckSnippetUtils.java	Mon Feb 11 10:41:29 2013 +0100
@@ -41,7 +41,7 @@
 
     static boolean checkSecondarySubType(Word t, Word s) {
         // if (S.cache == T) return true
-        if (s.readWord(secondarySuperCacheOffset()) == t) {
+        if (s.readWord(secondarySuperCacheOffset()).equal(t)) {
             cacheHit.inc();
             return true;
         }
@@ -55,7 +55,7 @@
         boolean primary = superCheckOffset != secondarySuperCacheOffset();
 
         // if (T = S[off]) return true
-        if (s.readWord(superCheckOffset) == t) {
+        if (s.readWord(superCheckOffset).equal(t)) {
             if (primary) {
                 cacheHit.inc();
             } else {
@@ -75,7 +75,7 @@
 
     private static boolean checkSelfAndSupers(Word t, Word s) {
         // if (T == S) return true
-        if (s == t) {
+        if (s.equal(t)) {
             T_equals_S.inc();
             return true;
         }
@@ -84,7 +84,7 @@
         Word secondarySupers = s.readWord(secondarySupersOffset());
         int length = secondarySupers.readInt(metaspaceArrayLengthOffset());
         for (int i = 0; i < length; i++) {
-            if (t == loadWordElement(secondarySupers, i)) {
+            if (t.equal(loadWordElement(secondarySupers, i))) {
                 probability(NOT_LIKELY_PROBABILITY);
                 s.writeWord(secondarySuperCacheOffset(), t);
                 secondariesHit.inc();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Mon Feb 11 10:41:29 2013 +0100
@@ -80,7 +80,7 @@
         // check that array length is small enough for fast path.
         if (length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) {
             Word memory = refillAllocate(intArrayHub, sizeInBytes, log);
-            if (memory != Word.zero()) {
+            if (memory.notEqual(0)) {
                 log(log, "newArray: allocated new array at %p\n", memory);
                 formatArray(hub, sizeInBytes, length, headerSize, memory, Word.unsigned(arrayPrototypeMarkWord()), true);
                 return verifyOop(memory.toObject());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Mon Feb 11 10:41:29 2013 +0100
@@ -71,7 +71,7 @@
         if (!forceSlowPath() && inlineContiguousAllocationSupported()) {
             if (hub.readInt(klassStateOffset()) == klassStateFullyInitialized()) {
                 Word memory = refillAllocate(intArrayHub, sizeInBytes, log);
-                if (memory != Word.zero()) {
+                if (memory.notEqual(0)) {
                     Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
                     memory.writeWord(markOffset(), prototypeMarkWord);
                     memory.writeWord(hubOffset(), hub);
@@ -129,7 +129,7 @@
 
             // if TLAB is currently allocated (top or end != null) then
             // fill [top, end + alignment_reserve) with array object
-            if (top != Word.zero()) {
+            if (top.notEqual(0)) {
                 int headerSize = arrayBaseOffset(Kind.Int);
                 // just like the HotSpot assembler stubs, assumes that tlabFreeSpaceInInts fits in
                 // an int
@@ -147,7 +147,7 @@
             Word tlabRefillSizeInBytes = tlabRefillSizeInWords.multiply(wordSize());
             // allocate new TLAB, address returned in top
             top = edenAllocate(tlabRefillSizeInBytes, log);
-            if (top != Word.zero()) {
+            if (top.notEqual(0)) {
                 thread.writeWord(threadTlabStartOffset(), top);
                 thread.writeWord(threadTlabTopOffset(), top);
 
@@ -195,7 +195,7 @@
                 return Word.zero();
             }
 
-            if (compareAndSwap(heapTopAddress, 0, heapTop, newHeapTop) == heapTop) {
+            if (compareAndSwap(heapTopAddress, 0, heapTop, newHeapTop).equal(heapTop)) {
                 return heapTop;
             }
         }
--- a/graal/com.oracle.graal.interpreter/overview.html	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html>
-<head>
-<!--
-
-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.  Oracle designates this
-particular file as subject to the "Classpath" exception as provided
-by Oracle in the LICENSE file that accompanied this code.
-
-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.
--->
-
-</head>
-<body>
-
-Documentation for the <code>com.oracle.graal.interpreter</code> project.
-
-</body>
-</html>
--- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1679 +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 java.util.*;
-
-import com.oracle.graal.api.interpreter.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.bytecode.*;
-
-/**
- * High-level bytecode interpreter that executes on top of Java. Java native methods are executed
- * using the {@link com.oracle.graal.api.interpreter.RuntimeInterpreterInterface}.
- */
-@SuppressWarnings("static-method")
-public final class BytecodeInterpreter implements Interpreter {
-
-    private static final String OPTION_MAX_STACK_SIZE = "maxStackSize";
-    private static final boolean TRACE = false;
-    private static final boolean TRACE_BYTE_CODE = false;
-
-    private static final int DEFAULT_MAX_STACK_SIZE = 1500;
-
-    private static final int NEXT = -1;
-    private static final int BRANCH = -2;
-    private static final int RETURN = -3;
-    private static final int CALL = -4;
-
-    private InterpreterFrame callFrame;
-
-    private Map<ResolvedJavaMethod, MethodRedirectionInfo> methodDelegates;
-
-    private int maxStackFrames;
-
-    private ResolvedJavaMethod rootMethod;
-    private RuntimeInterpreterInterface runtimeInterface;
-    private MetaAccessProvider metaAccessProvider;
-
-    public boolean initialize(String args) {
-        methodDelegates = new HashMap<>();
-        maxStackFrames = DEFAULT_MAX_STACK_SIZE;
-
-        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() + ".");
-        }
-
-        this.rootMethod = resolveRootMethod();
-        registerDelegates();
-        return parseArguments(args);
-    }
-
-    @Override
-    public void setOption(String name, String value) {
-        if (name != null && name.equals(OPTION_MAX_STACK_SIZE)) {
-            this.maxStackFrames = Integer.parseInt(value);
-        }
-    }
-
-    private void registerDelegates() {
-        addDelegate(findMethod(Throwable.class, "fillInStackTrace"), new InterpreterCallable() {
-
-            @Override
-            public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable {
-                setBackTrace(caller, (Throwable) arguments[0], createStackTraceElements(caller, runtimeInterface));
-                return null;
-            }
-        });
-        addDelegate(findMethod(Throwable.class, "getStackTraceDepth"), new InterpreterCallable() {
-
-            @Override
-            public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable {
-                StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]);
-                if (elements != null) {
-                    return elements.length;
-                }
-                return 0;
-            }
-        });
-        addDelegate(findMethod(Throwable.class, "getStackTraceElement", int.class), new InterpreterCallable() {
-
-            @Override
-            public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable {
-                StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]);
-                if (elements != null) {
-                    Integer index = (Integer) arguments[0];
-                    if (index != null) {
-                        return elements[index];
-                    }
-                }
-                return null;
-            }
-        });
-    }
-
-    @SuppressWarnings("unused")
-    private boolean parseArguments(String stringArgs) {
-        // TODO: parse the arguments
-        return true;
-    }
-
-    public void setMaxStackFrames(int maxStackSize) {
-        this.maxStackFrames = maxStackSize;
-    }
-
-    public int getMaxStackFrames() {
-        return maxStackFrames;
-    }
-
-    public void addDelegate(Method method, InterpreterCallable callable) {
-        ResolvedJavaMethod resolvedMethod = metaAccessProvider.lookupJavaMethod(method);
-        if (methodDelegates.containsKey(resolvedMethod)) {
-            throw new IllegalArgumentException("Delegate for method " + method + " already added.");
-        }
-
-        methodDelegates.put(resolvedMethod, new MethodRedirectionInfo(callable));
-    }
-
-    public void removeDelegate(Method method) {
-        methodDelegates.remove(metaAccessProvider.lookupJavaMethod(method));
-    }
-
-    @Override
-    public Object execute(ResolvedJavaMethod method, Object... boxedArguments) throws Throwable {
-        try {
-            boolean receiver = hasReceiver(method);
-            Signature signature = method.getSignature();
-            assert boxedArguments != null;
-            assert signature.getParameterCount(receiver) == boxedArguments.length;
-
-            if (TRACE) {
-                trace(0, "Executing root method " + method);
-            }
-
-            InterpreterFrame rootFrame = new InterpreterFrame(rootMethod, signature.getParameterSlots(true));
-            rootFrame.pushObject(this);
-            rootFrame.pushObject(method);
-            rootFrame.pushObject(boxedArguments);
-
-            int index = 0;
-            if (receiver) {
-                pushAsObject(rootFrame, Kind.Object, boxedArguments[index]);
-                index++;
-            }
-
-            for (int i = 0; index < boxedArguments.length; i++, index++) {
-                pushAsObject(rootFrame, signature.getParameterKind(i), boxedArguments[index]);
-            }
-
-            InterpreterFrame frame = rootFrame.create(method, receiver);
-            executeRoot(rootFrame, frame);
-            return popAsObject(rootFrame, signature.getReturnKind());
-        } catch (Exception e) {
-            // TODO (chaeubl): remove this exception handler (only used for debugging)
-            throw e;
-        }
-    }
-
-    public Object execute(Method javaMethod, Object... boxedArguments) throws Throwable {
-        return execute(metaAccessProvider.lookupJavaMethod(javaMethod), boxedArguments);
-    }
-
-    private boolean hasReceiver(ResolvedJavaMethod method) {
-        return !Modifier.isStatic(method.getModifiers());
-    }
-
-    private void executeRoot(InterpreterFrame root, InterpreterFrame frame) throws Throwable {
-        // TODO reflection redirection
-        InterpreterFrame prevFrame = frame;
-        InterpreterFrame currentFrame = frame;
-        BytecodeStream bs = new BytecodeStream(currentFrame.getMethod().getCode());
-        if (TRACE) {
-            traceCall(frame, "Call");
-        }
-        while (currentFrame != root) {
-            if (prevFrame != currentFrame) {
-                bs = new BytecodeStream(currentFrame.getMethod().getCode());
-            }
-            bs.setBCI(currentFrame.getBCI());
-
-            prevFrame = currentFrame;
-            currentFrame = loop(root, prevFrame, bs);
-        }
-        assert callFrame == null;
-    }
-
-    private InterpreterFrame loop(InterpreterFrame root, final InterpreterFrame frame, final BytecodeStream bs) throws Throwable {
-        try {
-            while (true) {
-                int result = executeInstruction(frame, bs);
-                switch (result) {
-                    case NEXT:
-                        bs.next();
-                        break;
-                    case RETURN:
-                        return popFrame(frame);
-                    case CALL:
-                        return allocateFrame(frame, bs);
-                    case BRANCH:
-                        bs.setBCI(bs.readBranchDest());
-                        break;
-                    default:
-                        // the outcome depends on stack values
-                        assert result >= 0 : "negative branch target";
-                        bs.setBCI(result);
-                        break;
-                }
-            }
-        } catch (Throwable t) {
-            if (TRACE) {
-                traceOp(frame, "Exception " + t.toString());
-            }
-            updateStackTrace(frame, t);
-
-            // frame bci needs to be in sync when handling exceptions
-            frame.setBCI(bs.currentBCI());
-
-            InterpreterFrame handlerFrame = handleThrowable(root, frame, t);
-            if (handlerFrame == null) {
-                // matched root we just throw it again.
-                throw t;
-            } else {
-                if (TRACE) {
-                    traceOp(frame, "Handler found " + handlerFrame.getMethod() + ":" + handlerFrame.getBCI());
-                }
-                // update bci from frame
-                bs.setBCI(handlerFrame.getBCI());
-
-                // continue execution on the found frame
-                return handlerFrame;
-            }
-        } finally {
-            // TODO may be not necessary.
-            frame.setBCI(bs.currentBCI());
-        }
-    }
-
-    private int executeInstruction(InterpreterFrame frame, BytecodeStream bs) throws Throwable {
-        if (TRACE_BYTE_CODE) {
-            traceOp(frame, bs.currentBCI() + ": " + Bytecodes.baseNameOf(bs.currentBC()));
-        }
-        switch (bs.currentBC()) {
-            case Bytecodes.NOP:
-                break;
-            case Bytecodes.ACONST_NULL:
-                frame.pushObject(null);
-                break;
-            case Bytecodes.ICONST_M1:
-                frame.pushInt(-1);
-                break;
-            case Bytecodes.ICONST_0:
-                frame.pushInt(0);
-                break;
-            case Bytecodes.ICONST_1:
-                frame.pushInt(1);
-                break;
-            case Bytecodes.ICONST_2:
-                frame.pushInt(2);
-                break;
-            case Bytecodes.ICONST_3:
-                frame.pushInt(3);
-                break;
-            case Bytecodes.ICONST_4:
-                frame.pushInt(4);
-                break;
-            case Bytecodes.ICONST_5:
-                frame.pushInt(5);
-                break;
-            case Bytecodes.LCONST_0:
-                frame.pushLong(0L);
-                break;
-            case Bytecodes.LCONST_1:
-                frame.pushLong(1L);
-                break;
-            case Bytecodes.FCONST_0:
-                frame.pushFloat(0.0F);
-                break;
-            case Bytecodes.FCONST_1:
-                frame.pushFloat(1.0F);
-                break;
-            case Bytecodes.FCONST_2:
-                frame.pushFloat(2.0F);
-                break;
-            case Bytecodes.DCONST_0:
-                frame.pushDouble(0.0D);
-                break;
-            case Bytecodes.DCONST_1:
-                frame.pushDouble(1.0D);
-                break;
-            case Bytecodes.BIPUSH:
-                frame.pushInt(bs.readByte());
-                break;
-            case Bytecodes.SIPUSH:
-                frame.pushInt(bs.readShort());
-                break;
-            case Bytecodes.LDC:
-            case Bytecodes.LDC_W:
-            case Bytecodes.LDC2_W:
-                pushCPConstant(frame, bs.readCPI());
-                break;
-            case Bytecodes.ILOAD:
-                frame.pushInt(frame.getInt(frame.resolveLocalIndex(bs.readLocalIndex())));
-                break;
-            case Bytecodes.LLOAD:
-                frame.pushLong(frame.getLong(frame.resolveLocalIndex(bs.readLocalIndex())));
-                break;
-            case Bytecodes.FLOAD:
-                frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(bs.readLocalIndex())));
-                break;
-            case Bytecodes.DLOAD:
-                frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(bs.readLocalIndex())));
-                break;
-            case Bytecodes.ALOAD:
-                frame.pushObject(frame.getObject(frame.resolveLocalIndex(bs.readLocalIndex())));
-                break;
-            case Bytecodes.ILOAD_0:
-                frame.pushInt(frame.getInt(frame.resolveLocalIndex(0)));
-                break;
-            case Bytecodes.ILOAD_1:
-                frame.pushInt(frame.getInt(frame.resolveLocalIndex(1)));
-                break;
-            case Bytecodes.ILOAD_2:
-                frame.pushInt(frame.getInt(frame.resolveLocalIndex(2)));
-                break;
-            case Bytecodes.ILOAD_3:
-                frame.pushInt(frame.getInt(frame.resolveLocalIndex(3)));
-                break;
-            case Bytecodes.LLOAD_0:
-                frame.pushLong(frame.getLong(frame.resolveLocalIndex(0)));
-                break;
-            case Bytecodes.LLOAD_1:
-                frame.pushLong(frame.getLong(frame.resolveLocalIndex(1)));
-                break;
-            case Bytecodes.LLOAD_2:
-                frame.pushLong(frame.getLong(frame.resolveLocalIndex(2)));
-                break;
-            case Bytecodes.LLOAD_3:
-                frame.pushLong(frame.getLong(frame.resolveLocalIndex(3)));
-                break;
-            case Bytecodes.FLOAD_0:
-                frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(0)));
-                break;
-            case Bytecodes.FLOAD_1:
-                frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(1)));
-                break;
-            case Bytecodes.FLOAD_2:
-                frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(2)));
-                break;
-            case Bytecodes.FLOAD_3:
-                frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(3)));
-                break;
-            case Bytecodes.DLOAD_0:
-                frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(0)));
-                break;
-            case Bytecodes.DLOAD_1:
-                frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(1)));
-                break;
-            case Bytecodes.DLOAD_2:
-                frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(2)));
-                break;
-            case Bytecodes.DLOAD_3:
-                frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(3)));
-                break;
-            case Bytecodes.ALOAD_0:
-                frame.pushObject(frame.getObject(frame.resolveLocalIndex(0)));
-                break;
-            case Bytecodes.ALOAD_1:
-                frame.pushObject(frame.getObject(frame.resolveLocalIndex(1)));
-                break;
-            case Bytecodes.ALOAD_2:
-                frame.pushObject(frame.getObject(frame.resolveLocalIndex(2)));
-                break;
-            case Bytecodes.ALOAD_3:
-                frame.pushObject(frame.getObject(frame.resolveLocalIndex(3)));
-                break;
-            case Bytecodes.IALOAD:
-                frame.pushInt(runtimeInterface.getArrayInt(frame.popInt(), frame.popObject()));
-                break;
-            case Bytecodes.LALOAD:
-                frame.pushLong(runtimeInterface.getArrayLong(frame.popInt(), frame.popObject()));
-                break;
-            case Bytecodes.FALOAD:
-                frame.pushFloat(runtimeInterface.getArrayFloat(frame.popInt(), frame.popObject()));
-                break;
-            case Bytecodes.DALOAD:
-                frame.pushDouble(runtimeInterface.getArrayDouble(frame.popInt(), frame.popObject()));
-                break;
-            case Bytecodes.AALOAD:
-                frame.pushObject(runtimeInterface.getArrayObject(frame.popInt(), frame.popObject()));
-                break;
-            case Bytecodes.BALOAD:
-                frame.pushInt(runtimeInterface.getArrayByte(frame.popInt(), frame.popObject()));
-                break;
-            case Bytecodes.CALOAD:
-                frame.pushInt(runtimeInterface.getArrayChar(frame.popInt(), frame.popObject()));
-                break;
-            case Bytecodes.SALOAD:
-                frame.pushInt(runtimeInterface.getArrayShort(frame.popInt(), frame.popObject()));
-                break;
-            case Bytecodes.ISTORE:
-                frame.setInt(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popInt());
-                break;
-            case Bytecodes.LSTORE:
-                frame.setLong(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popLong());
-                break;
-            case Bytecodes.FSTORE:
-                frame.setFloat(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popFloat());
-                break;
-            case Bytecodes.DSTORE:
-                frame.setDouble(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popDouble());
-                break;
-            case Bytecodes.ASTORE:
-                frame.setObject(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popObject());
-                break;
-            case Bytecodes.ISTORE_0:
-                frame.setInt(frame.resolveLocalIndex(0), frame.popInt());
-                break;
-            case Bytecodes.ISTORE_1:
-                frame.setInt(frame.resolveLocalIndex(1), frame.popInt());
-                break;
-            case Bytecodes.ISTORE_2:
-                frame.setInt(frame.resolveLocalIndex(2), frame.popInt());
-                break;
-            case Bytecodes.ISTORE_3:
-                frame.setInt(frame.resolveLocalIndex(3), frame.popInt());
-                break;
-            case Bytecodes.LSTORE_0:
-                frame.setLong(frame.resolveLocalIndex(0), frame.popLong());
-                break;
-            case Bytecodes.LSTORE_1:
-                frame.setLong(frame.resolveLocalIndex(1), frame.popLong());
-                break;
-            case Bytecodes.LSTORE_2:
-                frame.setLong(frame.resolveLocalIndex(2), frame.popLong());
-                break;
-            case Bytecodes.LSTORE_3:
-                frame.setLong(frame.resolveLocalIndex(3), frame.popLong());
-                break;
-            case Bytecodes.FSTORE_0:
-                frame.setFloat(frame.resolveLocalIndex(0), frame.popFloat());
-                break;
-            case Bytecodes.FSTORE_1:
-                frame.setFloat(frame.resolveLocalIndex(1), frame.popFloat());
-                break;
-            case Bytecodes.FSTORE_2:
-                frame.setFloat(frame.resolveLocalIndex(2), frame.popFloat());
-                break;
-            case Bytecodes.FSTORE_3:
-                frame.setFloat(frame.resolveLocalIndex(3), frame.popFloat());
-                break;
-            case Bytecodes.DSTORE_0:
-                frame.setDouble(frame.resolveLocalIndex(0), frame.popDouble());
-                break;
-            case Bytecodes.DSTORE_1:
-                frame.setDouble(frame.resolveLocalIndex(1), frame.popDouble());
-                break;
-            case Bytecodes.DSTORE_2:
-                frame.setDouble(frame.resolveLocalIndex(2), frame.popDouble());
-                break;
-            case Bytecodes.DSTORE_3:
-                frame.setDouble(frame.resolveLocalIndex(3), frame.popDouble());
-                break;
-            case Bytecodes.ASTORE_0:
-                frame.setObject(frame.resolveLocalIndex(0), frame.popObject());
-                break;
-            case Bytecodes.ASTORE_1:
-                frame.setObject(frame.resolveLocalIndex(1), frame.popObject());
-                break;
-            case Bytecodes.ASTORE_2:
-                frame.setObject(frame.resolveLocalIndex(2), frame.popObject());
-                break;
-            case Bytecodes.ASTORE_3:
-                frame.setObject(frame.resolveLocalIndex(3), frame.popObject());
-                break;
-            case Bytecodes.IASTORE:
-                runtimeInterface.setArrayInt(frame.popInt(), frame.popInt(), frame.popObject());
-                break;
-            case Bytecodes.LASTORE:
-                runtimeInterface.setArrayLong(frame.popLong(), frame.popInt(), frame.popObject());
-                break;
-            case Bytecodes.FASTORE:
-                runtimeInterface.setArrayFloat(frame.popFloat(), frame.popInt(), frame.popObject());
-                break;
-            case Bytecodes.DASTORE:
-                runtimeInterface.setArrayDouble(frame.popDouble(), frame.popInt(), frame.popObject());
-                break;
-            case Bytecodes.AASTORE:
-                runtimeInterface.setArrayObject(frame.popObject(), frame.popInt(), frame.popObject());
-                break;
-            case Bytecodes.BASTORE:
-                runtimeInterface.setArrayByte((byte) frame.popInt(), frame.popInt(), frame.popObject());
-                break;
-            case Bytecodes.CASTORE:
-                runtimeInterface.setArrayChar((char) frame.popInt(), frame.popInt(), frame.popObject());
-                break;
-            case Bytecodes.SASTORE:
-                runtimeInterface.setArrayShort((short) frame.popInt(), frame.popInt(), frame.popObject());
-                break;
-            case Bytecodes.POP:
-                frame.popVoid(1);
-                break;
-            case Bytecodes.POP2:
-                frame.popVoid(2);
-                break;
-            case Bytecodes.DUP:
-                frame.dup(1);
-                break;
-            case Bytecodes.DUP_X1:
-                frame.dupx1();
-                break;
-            case Bytecodes.DUP_X2:
-                frame.dupx2();
-                break;
-            case Bytecodes.DUP2:
-                frame.dup(2);
-                break;
-            case Bytecodes.DUP2_X1:
-                frame.dup2x1();
-                break;
-            case Bytecodes.DUP2_X2:
-                frame.dup2x2();
-                break;
-            case Bytecodes.SWAP:
-                frame.swapSingle();
-                break;
-            case Bytecodes.IADD:
-                frame.pushInt(frame.popInt() + frame.popInt());
-                break;
-            case Bytecodes.LADD:
-                frame.pushLong(frame.popLong() + frame.popLong());
-                break;
-            case Bytecodes.FADD:
-                frame.pushFloat(frame.popFloat() + frame.popFloat());
-                break;
-            case Bytecodes.DADD:
-                frame.pushDouble(frame.popDouble() + frame.popDouble());
-                break;
-            case Bytecodes.ISUB:
-                frame.pushInt(-frame.popInt() + frame.popInt());
-                break;
-            case Bytecodes.LSUB:
-                frame.pushLong(-frame.popLong() + frame.popLong());
-                break;
-            case Bytecodes.FSUB:
-                frame.pushFloat(-frame.popFloat() + frame.popFloat());
-                break;
-            case Bytecodes.DSUB:
-                frame.pushDouble(-frame.popDouble() + frame.popDouble());
-                break;
-            case Bytecodes.IMUL:
-                frame.pushInt(frame.popInt() * frame.popInt());
-                break;
-            case Bytecodes.LMUL:
-                frame.pushLong(frame.popLong() * frame.popLong());
-                break;
-            case Bytecodes.FMUL:
-                frame.pushFloat(frame.popFloat() * frame.popFloat());
-                break;
-            case Bytecodes.DMUL:
-                frame.pushDouble(frame.popDouble() * frame.popDouble());
-                break;
-            case Bytecodes.IDIV:
-                divInt(frame);
-                break;
-            case Bytecodes.LDIV:
-                divLong(frame);
-                break;
-            case Bytecodes.FDIV:
-                divFloat(frame);
-                break;
-            case Bytecodes.DDIV:
-                divDouble(frame);
-                break;
-            case Bytecodes.IREM:
-                remInt(frame);
-                break;
-            case Bytecodes.LREM:
-                remLong(frame);
-                break;
-            case Bytecodes.FREM:
-                remFloat(frame);
-                break;
-            case Bytecodes.DREM:
-                remDouble(frame);
-                break;
-            case Bytecodes.INEG:
-                frame.pushInt(-frame.popInt());
-                break;
-            case Bytecodes.LNEG:
-                frame.pushLong(-frame.popLong());
-                break;
-            case Bytecodes.FNEG:
-                frame.pushFloat(-frame.popFloat());
-                break;
-            case Bytecodes.DNEG:
-                frame.pushDouble(-frame.popDouble());
-                break;
-            case Bytecodes.ISHL:
-                shiftLeftInt(frame);
-                break;
-            case Bytecodes.LSHL:
-                shiftLeftLong(frame);
-                break;
-            case Bytecodes.ISHR:
-                shiftRightSignedInt(frame);
-                break;
-            case Bytecodes.LSHR:
-                shiftRightSignedLong(frame);
-                break;
-            case Bytecodes.IUSHR:
-                shiftRightUnsignedInt(frame);
-                break;
-            case Bytecodes.LUSHR:
-                shiftRightUnsignedLong(frame);
-                break;
-            case Bytecodes.IAND:
-                frame.pushInt(frame.popInt() & frame.popInt());
-                break;
-            case Bytecodes.LAND:
-                frame.pushLong(frame.popLong() & frame.popLong());
-                break;
-            case Bytecodes.IOR:
-                frame.pushInt(frame.popInt() | frame.popInt());
-                break;
-            case Bytecodes.LOR:
-                frame.pushLong(frame.popLong() | frame.popLong());
-                break;
-            case Bytecodes.IXOR:
-                frame.pushInt(frame.popInt() ^ frame.popInt());
-                break;
-            case Bytecodes.LXOR:
-                frame.pushLong(frame.popLong() ^ frame.popLong());
-                break;
-            case Bytecodes.IINC:
-                iinc(frame, bs);
-                break;
-            case Bytecodes.I2L:
-                frame.pushLong(frame.popInt());
-                break;
-            case Bytecodes.I2F:
-                frame.pushFloat(frame.popInt());
-                break;
-            case Bytecodes.I2D:
-                frame.pushDouble(frame.popInt());
-                break;
-            case Bytecodes.L2I:
-                frame.pushInt((int) frame.popLong());
-                break;
-            case Bytecodes.L2F:
-                frame.pushFloat(frame.popLong());
-                break;
-            case Bytecodes.L2D:
-                frame.pushDouble(frame.popLong());
-                break;
-            case Bytecodes.F2I:
-                frame.pushInt((int) frame.popFloat());
-                break;
-            case Bytecodes.F2L:
-                frame.pushLong((long) frame.popFloat());
-                break;
-            case Bytecodes.F2D:
-                frame.pushDouble(frame.popFloat());
-                break;
-            case Bytecodes.D2I:
-                frame.pushInt((int) frame.popDouble());
-                break;
-            case Bytecodes.D2L:
-                frame.pushLong((long) frame.popDouble());
-                break;
-            case Bytecodes.D2F:
-                frame.pushFloat((float) frame.popDouble());
-                break;
-            case Bytecodes.I2B:
-                frame.pushInt((byte) frame.popInt());
-                break;
-            case Bytecodes.I2C:
-                frame.pushInt((char) frame.popInt());
-                break;
-            case Bytecodes.I2S:
-                frame.pushInt((short) frame.popInt());
-                break;
-            case Bytecodes.LCMP:
-                compareLong(frame);
-                break;
-            case Bytecodes.FCMPL:
-                compareFloatLess(frame);
-                break;
-            case Bytecodes.FCMPG:
-                compareFloatGreater(frame);
-                break;
-            case Bytecodes.DCMPL:
-                compareDoubleLess(frame);
-                break;
-            case Bytecodes.DCMPG:
-                compareDoubleGreater(frame);
-                break;
-            case Bytecodes.IFEQ:
-                if (frame.popInt() == 0) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.IFNE:
-                if (frame.popInt() != 0) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.IFLT:
-                if (frame.popInt() < 0) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.IFGE:
-                if (frame.popInt() >= 0) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.IFGT:
-                if (frame.popInt() > 0) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.IFLE:
-                if (frame.popInt() <= 0) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.IF_ICMPEQ:
-                if (frame.popInt() == frame.popInt()) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.IF_ICMPNE:
-                if (frame.popInt() != frame.popInt()) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.IF_ICMPLT:
-                if (frame.popInt() > frame.popInt()) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.IF_ICMPGE:
-                if (frame.popInt() <= frame.popInt()) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.IF_ICMPGT:
-                if (frame.popInt() < frame.popInt()) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.IF_ICMPLE:
-                if (frame.popInt() >= frame.popInt()) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.IF_ACMPEQ:
-                if (frame.popObject() == frame.popObject()) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.IF_ACMPNE:
-                if (frame.popObject() != frame.popObject()) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.GOTO:
-            case Bytecodes.GOTO_W:
-                return BRANCH;
-            case Bytecodes.JSR:
-            case Bytecodes.JSR_W:
-                frame.pushInt(bs.currentBCI());
-                return BRANCH;
-            case Bytecodes.RET:
-                return frame.getInt(frame.resolveLocalIndex(bs.readLocalIndex()));
-            case Bytecodes.TABLESWITCH:
-                return tableSwitch(frame, bs);
-            case Bytecodes.LOOKUPSWITCH:
-                return lookupSwitch(frame, bs);
-            case Bytecodes.IRETURN:
-                frame.getParentFrame().pushInt(frame.popInt());
-                return RETURN;
-            case Bytecodes.LRETURN:
-                frame.getParentFrame().pushLong(frame.popLong());
-                return RETURN;
-            case Bytecodes.FRETURN:
-                frame.getParentFrame().pushFloat(frame.popFloat());
-                return RETURN;
-            case Bytecodes.DRETURN:
-                frame.getParentFrame().pushDouble(frame.popDouble());
-                return RETURN;
-            case Bytecodes.ARETURN:
-                frame.getParentFrame().pushObject(frame.popObject());
-                return RETURN;
-            case Bytecodes.RETURN:
-                return RETURN;
-            case Bytecodes.GETSTATIC:
-                getField(frame, null, bs.currentBC(), bs.readCPI());
-                break;
-            case Bytecodes.PUTSTATIC:
-                putStatic(frame, bs.readCPI());
-                break;
-            case Bytecodes.GETFIELD:
-                getField(frame, nullCheck(frame.popObject()), bs.currentBC(), bs.readCPI());
-                break;
-            case Bytecodes.PUTFIELD:
-                putField(frame, bs.readCPI());
-                break;
-            case Bytecodes.INVOKEVIRTUAL:
-                callFrame = invokeVirtual(frame, bs.readCPI());
-                if (callFrame == null) {
-                    break;
-                }
-                return CALL;
-            case Bytecodes.INVOKESPECIAL:
-                callFrame = invokeSpecial(frame, bs.readCPI());
-                if (callFrame == null) {
-                    break;
-                }
-                return CALL;
-            case Bytecodes.INVOKESTATIC:
-                callFrame = invokeStatic(frame, bs.readCPI());
-                if (callFrame == null) {
-                    break;
-                }
-                return CALL;
-            case Bytecodes.INVOKEINTERFACE:
-                callFrame = invokeInterface(frame, bs.readCPI());
-                if (callFrame == null) {
-                    break;
-                }
-                return CALL;
-            case Bytecodes.XXXUNUSEDXXX:
-                assert false : "unused bytecode used. behaviour unspecified.";
-                // nop
-                break;
-            case Bytecodes.NEW:
-                frame.pushObject(allocateInstance(frame, bs.readCPI()));
-                break;
-            case Bytecodes.NEWARRAY:
-                frame.pushObject(allocateNativeArray(frame, bs.readByte()));
-                break;
-            case Bytecodes.ANEWARRAY:
-                frame.pushObject(allocateArray(frame, bs.readCPI()));
-                break;
-            case Bytecodes.ARRAYLENGTH:
-                frame.pushInt(Array.getLength(nullCheck(frame.popObject())));
-                break;
-            case Bytecodes.ATHROW:
-                Throwable t = (Throwable) frame.popObject();
-                if ("break".equals(t.getMessage())) {
-                    t.printStackTrace();
-                }
-                throw t;
-            case Bytecodes.CHECKCAST:
-                checkCast(frame, bs.readCPI());
-                break;
-            case Bytecodes.INSTANCEOF:
-                instanceOf(frame, bs.readCPI());
-                break;
-            case Bytecodes.MONITORENTER:
-                runtimeInterface.monitorEnter(frame.popObject());
-                break;
-            case Bytecodes.MONITOREXIT:
-                runtimeInterface.monitorExit(frame.popObject());
-                break;
-            case Bytecodes.WIDE:
-                assert false;
-                break;
-            case Bytecodes.MULTIANEWARRAY:
-                frame.pushObject(allocateMultiArray(frame, bs.readCPI(), bs.readUByte(bs.currentBCI() + 3)));
-                break;
-            case Bytecodes.IFNULL:
-                if (frame.popObject() == null) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.IFNONNULL:
-                if (frame.popObject() != null) {
-                    return BRANCH;
-                }
-                break;
-            case Bytecodes.BREAKPOINT:
-                assert false : "no breakpoints supported at this time.";
-                break; // nop
-        }
-        return NEXT;
-    }
-
-    private InterpreterFrame handleThrowable(InterpreterFrame root, InterpreterFrame frame, Throwable t) {
-        ExceptionHandler handler;
-        InterpreterFrame currentFrame = frame;
-        do {
-            handler = resolveExceptionHandlers(currentFrame, currentFrame.getBCI(), t);
-            if (handler == null) {
-                // no handler found pop frame
-                // and continue searching
-                currentFrame = popFrame(currentFrame);
-            } else {
-                // found a handler -> execute it
-                currentFrame.setBCI(handler.getHandlerBCI());
-                currentFrame.popStack();
-                currentFrame.pushObject(t);
-                return currentFrame;
-            }
-        } while (handler == null && currentFrame != root);
-
-        // will throw exception up the interpreter
-        return null;
-    }
-
-    private void updateStackTrace(InterpreterFrame frame, Throwable t) {
-        StackTraceElement[] elements = getBackTrace(frame, t);
-        if (elements != null) {
-            setStackTrace(frame, t, elements);
-            setBackTrace(frame, t, null);
-        } else {
-            setBackTrace(frame, t, createStackTraceElements(frame, runtimeInterface));
-        }
-    }
-
-    private void setStackTrace(InterpreterFrame frame, Throwable t, StackTraceElement[] stackTrace) {
-        runtimeInterface.setFieldObject(stackTrace, t, findThrowableField(frame, "stackTrace"));
-    }
-
-    private StackTraceElement[] getBackTrace(InterpreterFrame frame, Throwable t) {
-        Object value = runtimeInterface.getFieldObject(t, findThrowableField(frame, "backtrace"));
-        if (value instanceof StackTraceElement[]) {
-            return (StackTraceElement[]) value;
-        }
-        return null;
-    }
-
-    private void setBackTrace(InterpreterFrame frame, Throwable t, StackTraceElement[] backtrace) {
-        runtimeInterface.setFieldObject(backtrace, t, findThrowableField(frame, "backtrace"));
-    }
-
-    private ExceptionHandler resolveExceptionHandlers(InterpreterFrame frame, int bci, Throwable t) {
-        ExceptionHandler[] handlers = frame.getMethod().getExceptionHandlers();
-        for (int i = 0; i < handlers.length; i++) {
-            ExceptionHandler handler = handlers[i];
-            if (bci >= handler.getStartBCI() && bci <= handler.getEndBCI()) {
-                ResolvedJavaType catchType = null;
-                if (!handler.isCatchAll()) {
-                    // exception handlers are similar to instanceof bytecodes, so we pass instanceof
-                    catchType = resolveType(frame, Bytecodes.INSTANCEOF, (char) handler.catchTypeCPI());
-                }
-
-                if (catchType == null || catchType.isInstance(Constant.forObject(t))) {
-                    // the first found exception handler is our exception handler
-                    return handler;
-                }
-            }
-        }
-        return null;
-    }
-
-    private Class<?> mirror(ResolvedJavaType type) {
-        return runtimeInterface.getMirror(type);
-    }
-
-    private InterpreterFrame allocateFrame(InterpreterFrame frame, BytecodeStream bs) {
-        try {
-            InterpreterFrame nextFrame = this.callFrame;
-
-            assert nextFrame != null;
-            assert nextFrame.getParentFrame() == frame;
-
-            // store bci when leaving method
-            frame.setBCI(bs.currentBCI());
-
-            if (TRACE) {
-                traceCall(nextFrame, "Call");
-            }
-            if (Modifier.isSynchronized(nextFrame.getMethod().getModifiers())) {
-                if (TRACE) {
-                    traceOp(frame, "Method monitor enter");
-                }
-                if (Modifier.isStatic(nextFrame.getMethod().getModifiers())) {
-                    runtimeInterface.monitorEnter(mirror(nextFrame.getMethod().getDeclaringClass()));
-                } else {
-                    Object enterObject = nextFrame.getObject(frame.resolveLocalIndex(0));
-                    assert enterObject != null;
-                    runtimeInterface.monitorEnter(enterObject);
-                }
-            }
-
-            return nextFrame;
-        } finally {
-            callFrame = null;
-            bs.next();
-        }
-    }
-
-    private InterpreterFrame popFrame(InterpreterFrame frame) {
-        InterpreterFrame parent = frame.getParentFrame();
-        if (Modifier.isSynchronized(frame.getMethod().getModifiers())) {
-            if (TRACE) {
-                traceOp(frame, "Method monitor exit");
-            }
-            if (Modifier.isStatic(frame.getMethod().getModifiers())) {
-                runtimeInterface.monitorExit(mirror(frame.getMethod().getDeclaringClass()));
-            } else {
-                Object exitObject = frame.getObject(frame.resolveLocalIndex(0));
-                if (exitObject != null) {
-                    runtimeInterface.monitorExit(exitObject);
-                }
-            }
-        }
-        if (TRACE) {
-            traceCall(frame, "Ret");
-        }
-
-        frame.dispose();
-        return parent;
-    }
-
-    private void traceOp(InterpreterFrame frame, String opName) {
-        trace(frame.depth(), opName);
-    }
-
-    private void traceCall(InterpreterFrame frame, String type) {
-        trace(frame.depth(), type + " " + frame.getMethod() + " - " + frame.getMethod().getSignature());
-    }
-
-    private void trace(int level, String message) {
-        StringBuilder builder = new StringBuilder();
-        for (int i = 0; i < level; i++) {
-            builder.append("  ");
-        }
-        builder.append(message);
-        System.out.println(builder);
-    }
-
-    private void divInt(InterpreterFrame frame) {
-        int dividend = frame.popInt();
-        int divisor = frame.popInt();
-        frame.pushInt(divisor / dividend);
-    }
-
-    private void divLong(InterpreterFrame frame) {
-        long dividend = frame.popLong();
-        long divisor = frame.popLong();
-        frame.pushLong(divisor / dividend);
-    }
-
-    private void divFloat(InterpreterFrame frame) {
-        float dividend = frame.popFloat();
-        float divisor = frame.popFloat();
-        frame.pushFloat(divisor / dividend);
-    }
-
-    private void divDouble(InterpreterFrame frame) {
-        double dividend = frame.popDouble();
-        double divisor = frame.popDouble();
-        frame.pushDouble(divisor / dividend);
-    }
-
-    private void remInt(InterpreterFrame frame) {
-        int dividend = frame.popInt();
-        int divisor = frame.popInt();
-        frame.pushInt(divisor % dividend);
-    }
-
-    private void remLong(InterpreterFrame frame) {
-        long dividend = frame.popLong();
-        long divisor = frame.popLong();
-        frame.pushLong(divisor % dividend);
-    }
-
-    private void remFloat(InterpreterFrame frame) {
-        float dividend = frame.popFloat();
-        float divisor = frame.popFloat();
-        frame.pushFloat(divisor % dividend);
-    }
-
-    private void remDouble(InterpreterFrame frame) {
-        double dividend = frame.popDouble();
-        double divisor = frame.popDouble();
-        frame.pushDouble(divisor % dividend);
-    }
-
-    private void shiftLeftInt(InterpreterFrame frame) {
-        int bits = frame.popInt();
-        int value = frame.popInt();
-        frame.pushInt(value << bits);
-    }
-
-    private void shiftLeftLong(InterpreterFrame frame) {
-        int bits = frame.popInt();
-        long value = frame.popLong();
-        frame.pushLong(value << bits);
-    }
-
-    private void shiftRightSignedInt(InterpreterFrame frame) {
-        int bits = frame.popInt();
-        int value = frame.popInt();
-        frame.pushInt(value >> bits);
-    }
-
-    private void shiftRightSignedLong(InterpreterFrame frame) {
-        int bits = frame.popInt();
-        long value = frame.popLong();
-        frame.pushLong(value >> bits);
-    }
-
-    private void shiftRightUnsignedInt(InterpreterFrame frame) {
-        int bits = frame.popInt();
-        int value = frame.popInt();
-        frame.pushInt(value >>> bits);
-    }
-
-    private void shiftRightUnsignedLong(InterpreterFrame frame) {
-        int bits = frame.popInt();
-        long value = frame.popLong();
-        frame.pushLong(value >>> bits);
-    }
-
-    private int lookupSwitch(InterpreterFrame frame, BytecodeStream bs) {
-        return lookupSearch(new BytecodeLookupSwitch(bs, bs.currentBCI()), frame.popInt());
-    }
-
-    /**
-     * Binary search implementation for the lookup switch.
-     */
-    private int lookupSearch(BytecodeLookupSwitch switchHelper, int key) {
-        int low = 0;
-        int high = switchHelper.numberOfCases() - 1;
-        while (low <= high) {
-            int mid = (low + high) >>> 1;
-            int midVal = switchHelper.keyAt(mid);
-
-            if (midVal < key) {
-                low = mid + 1;
-            } else if (midVal > key) {
-                high = mid - 1;
-            } else {
-                return switchHelper.bci() + switchHelper.offsetAt(mid); // key found
-            }
-        }
-        return switchHelper.defaultTarget(); // key not found.
-    }
-
-    private int tableSwitch(InterpreterFrame frame, BytecodeStream bs) {
-        BytecodeTableSwitch switchHelper = new BytecodeTableSwitch(bs, bs.currentBCI());
-
-        int low = switchHelper.lowKey();
-        int high = switchHelper.highKey();
-
-        assert low <= high;
-
-        int index = frame.popInt();
-        if (index < low || index > high) {
-            return switchHelper.defaultTarget();
-        } else {
-            return switchHelper.targetAt(index - low);
-        }
-    }
-
-    private void checkCast(InterpreterFrame frame, char cpi) {
-        frame.pushObject(mirror(resolveType(frame, Bytecodes.CHECKCAST, cpi)).cast(frame.popObject()));
-    }
-
-    private ResolvedJavaType resolveType(InterpreterFrame frame, int opcode, char cpi) {
-        ConstantPool constantPool = frame.getConstantPool();
-        constantPool.loadReferencedType(cpi, opcode);
-        return constantPool.lookupType(cpi, opcode).resolve(frame.getMethod().getDeclaringClass());
-    }
-
-    private ResolvedJavaType resolveType(InterpreterFrame frame, Class<?> javaClass) {
-        return metaAccessProvider.lookupJavaType(javaClass).resolve(frame.getMethod().getDeclaringClass());
-    }
-
-    private ResolvedJavaMethod resolveMethod(InterpreterFrame frame, int opcode, char cpi) {
-        ConstantPool constantPool = frame.getConstantPool();
-        constantPool.loadReferencedType(cpi, opcode);
-        return (ResolvedJavaMethod) constantPool.lookupMethod(cpi, opcode);
-    }
-
-    private ResolvedJavaField resolveField(InterpreterFrame frame, int opcode, char cpi) {
-        ConstantPool constantPool = frame.getConstantPool();
-        constantPool.loadReferencedType(cpi, opcode);
-        return (ResolvedJavaField) constantPool.lookupField(cpi, opcode);
-    }
-
-    private void instanceOf(InterpreterFrame frame, char cpi) {
-        frame.pushInt(resolveType(frame, Bytecodes.INSTANCEOF, cpi).isInstance(Constant.forObject(frame.popObject())) ? 1 : 0);
-    }
-
-    private void pushCPConstant(InterpreterFrame frame, char cpi) {
-        ResolvedJavaMethod method = frame.getMethod();
-        Object constant = method.getConstantPool().lookupConstant(cpi);
-
-        if (constant instanceof Constant) {
-            Constant c = ((Constant) constant);
-            switch (c.getKind()) {
-                case Int:
-                    frame.pushInt(c.asInt());
-                    break;
-                case Float:
-                    frame.pushFloat(c.asFloat());
-                    break;
-                case Object:
-                    frame.pushObject(c.asObject());
-                    break;
-                case Double:
-                    frame.pushDouble(c.asDouble());
-                    break;
-                case Long:
-                    frame.pushLong(c.asLong());
-                    break;
-                default:
-                    assert false : "unspecified case";
-            }
-        } else if (constant instanceof JavaType) {
-            frame.pushObject(mirror(((JavaType) constant).resolve(method.getDeclaringClass())));
-        } else {
-            assert false : "unexpected case";
-        }
-    }
-
-    private void compareLong(InterpreterFrame frame) {
-        long y = frame.popLong();
-        long x = frame.popLong();
-        frame.pushInt((x < y) ? -1 : ((x == y) ? 0 : 1));
-    }
-
-    private void compareDoubleGreater(InterpreterFrame frame) {
-        double y = frame.popDouble();
-        double x = frame.popDouble();
-        frame.pushInt(x < y ? -1 : ((x == y) ? 0 : 1));
-    }
-
-    private void compareDoubleLess(InterpreterFrame frame) {
-        double y = frame.popDouble();
-        double x = frame.popDouble();
-        frame.pushInt(x > y ? 1 : ((x == y) ? 0 : -1));
-    }
-
-    private void compareFloatGreater(InterpreterFrame frame) {
-        float y = frame.popFloat();
-        float x = frame.popFloat();
-        frame.pushInt(x < y ? -1 : ((x == y) ? 0 : 1));
-    }
-
-    private void compareFloatLess(InterpreterFrame frame) {
-        float y = frame.popFloat();
-        float x = frame.popFloat();
-        frame.pushInt(x > y ? 1 : ((x == y) ? 0 : -1));
-    }
-
-    private Object nullCheck(Object value) {
-        if (value == null) {
-            throw new NullPointerException();
-        }
-        return value;
-    }
-
-    private InterpreterFrame invokeStatic(InterpreterFrame frame, char cpi) throws Throwable {
-        return invoke(frame, resolveMethod(frame, Bytecodes.INVOKESTATIC, cpi), null);
-    }
-
-    private InterpreterFrame invokeInterface(InterpreterFrame frame, char cpi) throws Throwable {
-        return resolveAndInvoke(frame, resolveMethod(frame, Bytecodes.INVOKEINTERFACE, cpi));
-    }
-
-    private InterpreterFrame resolveAndInvoke(InterpreterFrame parent, ResolvedJavaMethod m) throws Throwable {
-        Object receiver = nullCheck(parent.peekReceiver(m));
-
-        ResolvedJavaMethod method = resolveType(parent, receiver.getClass()).resolveMethod(m);
-
-        if (method == null) {
-            throw new AbstractMethodError();
-        }
-
-        return invoke(parent, method, receiver);
-    }
-
-    private InterpreterFrame invokeVirtual(InterpreterFrame frame, char cpi) throws Throwable {
-        ResolvedJavaMethod m = resolveMethod(frame, Bytecodes.INVOKEVIRTUAL, cpi);
-        if (Modifier.isFinal(m.getModifiers())) {
-            return invoke(frame, m, nullCheck(frame.peekReceiver(m)));
-        } else {
-            return resolveAndInvoke(frame, m);
-        }
-    }
-
-    private InterpreterFrame invokeSpecial(InterpreterFrame frame, char cpi) throws Throwable {
-        ResolvedJavaMethod m = resolveMethod(frame, Bytecodes.INVOKESPECIAL, cpi);
-        return invoke(frame, m, nullCheck(frame.peekReceiver(m)));
-    }
-
-    private Object[] popArgumentsAsObject(InterpreterFrame frame, ResolvedJavaMethod method, boolean hasReceiver) {
-        Signature signature = method.getSignature();
-        int argumentCount = method.getSignature().getParameterCount(hasReceiver);
-        Object[] parameters = new Object[argumentCount];
-
-        int lastSignatureIndex = hasReceiver ? 1 : 0;
-        for (int i = argumentCount - 1; i >= lastSignatureIndex; i--) {
-            ResolvedJavaType type = signature.getParameterType(i - lastSignatureIndex, method.getDeclaringClass()).resolve(method.getDeclaringClass());
-            parameters[i] = popAsObject(frame, type.getKind());
-        }
-
-        if (hasReceiver) {
-            parameters[0] = frame.popObject();
-        }
-        return parameters;
-    }
-
-    private InterpreterFrame invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object receiver) throws Throwable {
-        if (caller.depth() >= maxStackFrames) {
-            throw new StackOverflowError("Maximum callstack of " + maxStackFrames + " exceeded.");
-        }
-
-        if (Modifier.isNative(method.getModifiers())) {
-            return invokeNativeMethodViaVM(caller, method, receiver != null);
-        } else {
-            MethodRedirectionInfo redirectedMethod = methodDelegates.get(method);
-            if (redirectedMethod != null) {
-                return invokeRedirectedMethodViaVM(caller, method, redirectedMethod, receiver != null);
-            } else {
-                return invokeOptimized(caller, method, receiver != null);
-            }
-        }
-    }
-
-    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.getSignature().getReturnKind(), 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.getSignature().getReturnKind(), 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 = getLastDimensionType(resolveType(frame, Bytecodes.MULTIANEWARRAY, cpi));
-
-        int[] dimensions = new int[dimension];
-        for (int i = dimension - 1; i >= 0; i--) {
-            dimensions[i] = frame.popInt();
-        }
-        return Array.newInstance(mirror(type), dimensions);
-    }
-
-    private ResolvedJavaType getLastDimensionType(ResolvedJavaType type) {
-        ResolvedJavaType result = type;
-        while (result.isArray()) {
-            result = result.getComponentType();
-        }
-        return result;
-    }
-
-    private Object allocateArray(InterpreterFrame frame, char cpi) {
-        ResolvedJavaType type = resolveType(frame, Bytecodes.ANEWARRAY, cpi);
-        return Array.newInstance(runtimeInterface.getMirror(type), frame.popInt());
-    }
-
-    private Object allocateNativeArray(InterpreterFrame frame, byte cpi) {
-        // the constants for the cpi are loosely defined and no real cpi indices.
-        switch (cpi) {
-            case 4:
-                return new byte[frame.popInt()];
-            case 8:
-                return new byte[frame.popInt()];
-            case 5:
-                return new char[frame.popInt()];
-            case 7:
-                return new double[frame.popInt()];
-            case 6:
-                return new float[frame.popInt()];
-            case 10:
-                return new int[frame.popInt()];
-            case 11:
-                return new long[frame.popInt()];
-            case 9:
-                return new short[frame.popInt()];
-            default:
-                assert false : "unexpected case";
-                return null;
-        }
-    }
-
-    private Object allocateInstance(InterpreterFrame frame, char cpi) throws InstantiationException {
-        return runtimeInterface.newObject(resolveType(frame, Bytecodes.NEW, cpi));
-    }
-
-    private void iinc(InterpreterFrame frame, BytecodeStream bs) {
-        int index = frame.resolveLocalIndex(bs.readLocalIndex());
-        frame.setInt(index, frame.getInt(index) + bs.readIncrement());
-    }
-
-    private void putStatic(InterpreterFrame frame, char cpi) {
-        putFieldStatic(frame, resolveField(frame, Bytecodes.PUTSTATIC, cpi));
-    }
-
-    private void putField(InterpreterFrame frame, char cpi) {
-        putFieldVirtual(frame, resolveField(frame, Bytecodes.PUTFIELD, cpi));
-    }
-
-    private void putFieldStatic(InterpreterFrame frame, ResolvedJavaField field) {
-        switch (field.getKind()) {
-            case Boolean:
-            case Byte:
-            case Char:
-            case Short:
-            case Int:
-                runtimeInterface.setFieldInt(frame.popInt(), null, field);
-                break;
-            case Double:
-                runtimeInterface.setFieldDouble(frame.popDouble(), null, field);
-                break;
-            case Float:
-                runtimeInterface.setFieldFloat(frame.popFloat(), null, field);
-                break;
-            case Long:
-                runtimeInterface.setFieldLong(frame.popLong(), null, field);
-                break;
-            case Object:
-                runtimeInterface.setFieldObject(frame.popObject(), null, field);
-                break;
-            default:
-                assert false : "unexpected case";
-        }
-    }
-
-    private void putFieldVirtual(InterpreterFrame frame, ResolvedJavaField field) {
-        switch (field.getKind()) {
-            case Boolean:
-            case Byte:
-            case Char:
-            case Short:
-            case Int:
-                runtimeInterface.setFieldInt(frame.popInt(), nullCheck(frame.popObject()), field);
-                break;
-            case Double:
-                runtimeInterface.setFieldDouble(frame.popDouble(), nullCheck(frame.popObject()), field);
-                break;
-            case Float:
-                runtimeInterface.setFieldFloat(frame.popFloat(), nullCheck(frame.popObject()), field);
-                break;
-            case Long:
-                runtimeInterface.setFieldLong(frame.popLong(), nullCheck(frame.popObject()), field);
-                break;
-            case Object:
-                runtimeInterface.setFieldObject(frame.popObject(), nullCheck(frame.popObject()), field);
-                break;
-            default:
-                assert false : "unexpected case";
-        }
-    }
-
-    private void getField(InterpreterFrame frame, Object base, int opcode, char cpi) {
-        ResolvedJavaField field = resolveField(frame, opcode, cpi);
-        switch (field.getKind()) {
-            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(runtimeInterface.getFieldInt(base, field));
-                break;
-            case Double:
-                frame.pushDouble(runtimeInterface.getFieldDouble(base, field));
-                break;
-            case Float:
-                frame.pushFloat(runtimeInterface.getFieldFloat(base, field));
-                break;
-            case Long:
-                frame.pushLong(runtimeInterface.getFieldLong(base, field));
-                break;
-            case Object:
-                frame.pushObject(runtimeInterface.getFieldObject(base, field));
-                break;
-            default:
-                assert false : "unexpected case";
-        }
-    }
-
-    private int pushAsObject(InterpreterFrame frame, Kind typeKind, Object value) {
-        switch (typeKind) {
-            case Int:
-                frame.pushInt((int) value);
-                break;
-            case Long:
-                frame.pushLong((long) value);
-                return 2;
-            case Boolean:
-                frame.pushInt(((boolean) value) ? 1 : 0);
-                break;
-            case Byte:
-                frame.pushInt((byte) value);
-                break;
-            case Char:
-                frame.pushInt((char) value);
-                break;
-            case Double:
-                frame.pushDouble((double) value);
-                return 2;
-            case Float:
-                frame.pushFloat((float) value);
-                break;
-            case Short:
-                frame.pushInt((short) value);
-                break;
-            case Object:
-                frame.pushObject(value);
-                break;
-            case Void:
-                return 0;
-            default:
-                assert false : "case not specified";
-        }
-        return 1;
-    }
-
-    private Object popAsObject(InterpreterFrame frame, Kind typeKind) {
-        switch (typeKind) {
-            case Boolean:
-                return frame.popInt() == 1 ? true : false;
-            case Byte:
-                return (byte) frame.popInt();
-            case Char:
-                return (char) frame.popInt();
-            case Double:
-                return frame.popDouble();
-            case Int:
-                return frame.popInt();
-            case Float:
-                return frame.popFloat();
-            case Long:
-                return frame.popLong();
-            case Short:
-                return (short) frame.popInt();
-            case Object:
-                return frame.popObject();
-            case Void:
-                return null;
-            default:
-                assert false : "unexpected case";
-        }
-        return null;
-    }
-
-    private ResolvedJavaMethod resolveRootMethod() {
-        try {
-            return metaAccessProvider.lookupJavaMethod(BytecodeInterpreter.class.getDeclaredMethod("execute", Method.class, Object[].class));
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private static Method findMethod(Class<?> clazz, String name, Class<?>... parameters) {
-        try {
-            return clazz.getDeclaredMethod(name, parameters);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private static StackTraceElement[] createStackTraceElements(InterpreterFrame frame, RuntimeInterpreterInterface runtimeInterface) {
-        InterpreterFrame tmp = frame;
-        List<StackTraceElement> elements = new ArrayList<>();
-        boolean first = false; // filter only first stack elements
-        while (tmp != null) {
-            if (first || !filterStackElement(tmp, runtimeInterface)) {
-                first = true;
-                elements.add(tmp.getMethod().asStackTraceElement(tmp.getBCI()));
-            }
-            tmp = tmp.getParentFrame();
-        }
-        return elements.toArray(new StackTraceElement[elements.size()]);
-    }
-
-    private static boolean filterStackElement(InterpreterFrame frame, RuntimeInterpreterInterface runtimeInterface) {
-        return Throwable.class.isAssignableFrom(runtimeInterface.getMirror(frame.getMethod().getDeclaringClass()));
-    }
-
-    private ResolvedJavaField findThrowableField(InterpreterFrame frame, String name) {
-        ResolvedJavaType throwableType = resolveType(frame, Throwable.class);
-        ResolvedJavaField[] fields = throwableType.getInstanceFields(false);
-        for (int i = 0; i < fields.length; i++) {
-            if (fields[i].getName().equals(name)) {
-                return fields[i];
-            }
-        }
-        assert false;
-        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/Frame.java	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +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.*;
-
-public class Frame {
-
-    public static final Object[] EMPTY_ARRAY = new Object[0];
-    public static final int PARENT_FRAME_SLOT = 0;
-    public static final int MIN_FRAME_SIZE = 1;
-    private static final Unsafe unsafe = getUnsafe();
-
-    protected final Object[] locals;
-    protected final long[] primitiveLocals;
-
-    public Frame(int numLocals, Frame parent) {
-        assert numLocals >= MIN_FRAME_SIZE;
-        this.locals = new Object[numLocals];
-        this.locals[PARENT_FRAME_SLOT] = parent;
-        this.primitiveLocals = new long[numLocals];
-    }
-
-    public Frame(int numLocals) {
-        this(numLocals, null);
-    }
-
-    public Object getObject(int index) {
-        return locals[index];
-    }
-
-    public void setObject(int index, Object value) {
-        locals[index] = value;
-    }
-
-    public float getFloat(int index) {
-        return unsafe.getFloat(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET);
-    }
-
-    public void setFloat(int index, float value) {
-        unsafe.putFloat(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value);
-    }
-
-    public long getLong(int index) {
-        return unsafe.getLong(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET);
-    }
-
-    public void setLong(int index, long value) {
-        unsafe.putLong(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value);
-    }
-
-    public int getInt(int index) {
-        return unsafe.getInt(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET);
-    }
-
-    public void setInt(int index, int value) {
-        unsafe.putInt(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value);
-    }
-
-    public double getDouble(int index) {
-        return unsafe.getDouble(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET);
-    }
-
-    public void setDouble(int index, double value) {
-        unsafe.putDouble(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value);
-    }
-
-    public static Frame getParentFrame(Frame frame, int level) {
-        assert level >= 0;
-        if (level == 0) {
-            return frame;
-        } else {
-            return getParentFrame((Frame) frame.getObject(PARENT_FRAME_SLOT), level - 1);
-        }
-    }
-
-    public static Frame getTopFrame(Frame frame) {
-        Frame parentFrame = (Frame) frame.getObject(PARENT_FRAME_SLOT);
-        if (parentFrame == null) {
-            return frame;
-        } else {
-            return getTopFrame(parentFrame);
-        }
-    }
-
-    public static Object[] getArguments(Frame frame, int argOffset) {
-        return (Object[]) frame.getObject(argOffset);
-    }
-
-    public int size() {
-        return locals.length;
-    }
-
-    @SuppressWarnings("unused")
-    private boolean indexExists(int index) {
-        return index >= 0 && index < locals.length;
-    }
-
-    private static Unsafe getUnsafe() {
-        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.interpreter/src/com/oracle/graal/interpreter/InterpreterCallable.java	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +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 com.oracle.graal.api.meta.*;
-
-public interface InterpreterCallable {
-
-    // static final fields
-    String INTERPRETER_CALLABLE_INVOKE_NAME = "invoke";
-    Class<?>[] INTERPRETER_CALLABLE_INVOKE_SIGNATURE = {InterpreterFrame.class, ResolvedJavaMethod.class, Object[].class};
-
-    // methods
-    Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable;
-}
--- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterException.java	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +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;
-
-/**
- * Thrown if executed byte code caused an error in {@link BytecodeInterpreter}. The actual execution
- * exception is accessible using {@link #getCause()} or {@link #getExecutionThrowable()}.
- */
-public class InterpreterException extends RuntimeException {
-
-    private static final long serialVersionUID = 1L;
-
-    public InterpreterException(Throwable cause) {
-        super(cause);
-    }
-
-    public Throwable getExecutionThrowable() {
-        return getCause();
-    }
-
-}
--- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterFrame.java	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,353 +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.util.*;
-
-import com.oracle.graal.api.meta.*;
-
-public class InterpreterFrame extends Frame {
-
-    public static final int BASE_LENGTH = 3;
-
-    private static final int METHOD_FRAME_SLOT = 1;
-    private static final int BCI_FRAME_SLOT = 2;
-
-    private static final int DOUBLE = 2;
-    private static final int SINGLE = 1;
-
-    /** Pointer to the top-most stack frame element. */
-    private int depth;
-    private int tos;
-
-    public InterpreterFrame(ResolvedJavaMethod method, int additionalStackSpace) {
-        this(method, null, additionalStackSpace, 0);
-    }
-
-    private InterpreterFrame(ResolvedJavaMethod method, InterpreterFrame parent, int additionalStackSpace, int depth) {
-        super(method.getMaxLocals() + method.getMaxStackSize() + BASE_LENGTH + additionalStackSpace, parent);
-        setMethod(method);
-        setBCI(0);
-        this.depth = depth;
-        this.tos = BASE_LENGTH;
-    }
-
-    public InterpreterFrame create(ResolvedJavaMethod method, boolean hasReceiver) {
-        InterpreterFrame frame = new InterpreterFrame(method, this, 0, this.depth + 1);
-        int length = method.getSignature().getParameterSlots(hasReceiver);
-
-        frame.pushVoid(method.getMaxLocals());
-        if (length > 0) {
-            copyArguments(frame, length);
-            popVoid(length);
-        }
-
-        return frame;
-    }
-
-    public int resolveLocalIndex(int index) {
-        return BASE_LENGTH + index;
-    }
-
-    public int depth() {
-        return depth;
-    }
-
-    private int stackTos() {
-        return BASE_LENGTH + getMethod().getMaxLocals();
-    }
-
-    private void copyArguments(InterpreterFrame dest, int length) {
-        System.arraycopy(locals, tosSingle(length - 1), dest.locals, BASE_LENGTH, length);
-        System.arraycopy(primitiveLocals, tosSingle(length - 1), dest.primitiveLocals, BASE_LENGTH, length);
-    }
-
-    public Object peekReceiver(ResolvedJavaMethod method) {
-        return getObject(tosSingle(method.getSignature().getParameterSlots(false)));
-    }
-
-    public void pushBoth(Object oValue, int intValue) {
-        incrementTos(SINGLE);
-        setObject(tosSingle(0), oValue);
-        setInt(tosSingle(0), intValue);
-    }
-
-    public void pushBoth(Object oValue, long longValue) {
-        incrementTos(SINGLE);
-        setObject(tosSingle(0), oValue);
-        setLong(tosSingle(0), longValue);
-    }
-
-    public void pushObject(Object value) {
-        incrementTos(SINGLE);
-        setObject(tosSingle(0), value);
-    }
-
-    public void pushInt(int value) {
-        incrementTos(SINGLE);
-        setInt(tosSingle(0), value);
-    }
-
-    public void pushDouble(double value) {
-        incrementTos(DOUBLE);
-        setDouble(tosDouble(0), value);
-    }
-
-    public void pushFloat(float value) {
-        incrementTos(SINGLE);
-        setFloat(tosSingle(0), value);
-    }
-
-    public void pushLong(long value) {
-        incrementTos(DOUBLE);
-        setLong(tosDouble(0), value);
-    }
-
-    public int popInt() {
-        int value = getInt(tosSingle(0));
-        decrementTos(SINGLE);
-        return value;
-    }
-
-    public double popDouble() {
-        double value = getDouble(tosDouble(0));
-        decrementTos(DOUBLE);
-        return value;
-    }
-
-    public float popFloat() {
-        float value = getFloat(tosSingle(0));
-        decrementTos(SINGLE);
-        return value;
-    }
-
-    public long popLong() {
-        long value = getLong(tosDouble(0));
-        decrementTos(DOUBLE);
-        return value;
-    }
-
-    public Object popObject() {
-        Object value = getObject(tosSingle(0));
-        decrementTos(SINGLE);
-        return value;
-    }
-
-    public void swapSingle() {
-        int tmpInt = getInt(tosSingle(1));
-        Object tmpObject = getObject(tosSingle(1));
-
-        setInt(tosSingle(1), getInt(tosSingle(0)));
-        setObject(tosSingle(1), getObject(tosSingle(0)));
-
-        setInt(tosSingle(0), tmpInt);
-        setObject(tosSingle(0), tmpObject);
-    }
-
-    public void dupx1() {
-        long tosLong = getLong(tosSingle(0));
-        Object tosObject = getObject(tosSingle(0));
-
-        swapSingle();
-
-        pushBoth(tosObject, tosLong);
-    }
-
-    public void dup2x1() {
-        long tosLong2 = getLong(tosSingle(2));
-        Object tosObject2 = getObject(tosSingle(2));
-        long tosLong1 = getLong(tosSingle(1));
-        Object tosObject1 = getObject(tosSingle(1));
-        long tosLong0 = getLong(tosSingle(0));
-        Object tosObject0 = getObject(tosSingle(0));
-
-        popVoid(3);
-
-        pushBoth(tosObject1, tosLong1);
-        pushBoth(tosObject0, tosLong0);
-
-        pushBoth(tosObject2, tosLong2);
-
-        pushBoth(tosObject1, tosLong1);
-        pushBoth(tosObject0, tosLong0);
-    }
-
-    public void dup2x2() {
-        long tosLong3 = getLong(tosSingle(3));
-        Object tosObject3 = getObject(tosSingle(3));
-        long tosLong2 = getLong(tosSingle(2));
-        Object tosObject2 = getObject(tosSingle(2));
-        long tosLong1 = getLong(tosSingle(1));
-        Object tosObject1 = getObject(tosSingle(1));
-        long tosLong0 = getLong(tosSingle(0));
-        Object tosObject0 = getObject(tosSingle(0));
-
-        popVoid(4);
-
-        pushBoth(tosObject1, tosLong1);
-        pushBoth(tosObject0, tosLong0);
-
-        pushBoth(tosObject3, tosLong3);
-        pushBoth(tosObject2, tosLong2);
-
-        pushBoth(tosObject1, tosLong1);
-        pushBoth(tosObject0, tosLong0);
-    }
-
-    public void dupx2() {
-        long tosLong2 = getLong(tosSingle(2));
-        Object tosObject2 = getObject(tosSingle(2));
-        long tosLong1 = getLong(tosSingle(1));
-        Object tosObject1 = getObject(tosSingle(1));
-        long tosLong0 = getLong(tosSingle(0));
-        Object tosObject0 = getObject(tosSingle(0));
-
-        popVoid(3);
-
-        pushBoth(tosObject0, tosLong0);
-        pushBoth(tosObject2, tosLong2);
-        pushBoth(tosObject1, tosLong1);
-        pushBoth(tosObject0, tosLong0);
-    }
-
-    public void dup(int length) {
-        assert length > 0;
-        for (int i = 0; i < length; i++) {
-            long valueN1 = getLong(tosSingle(length - i - 1));
-            Object valueO1 = getObject(tosSingle(length - i - 1));
-
-            pushVoid(1);
-
-            setLong(tosSingle(0), valueN1);
-            setObject(tosSingle(0), valueO1);
-        }
-    }
-
-    private void incrementTos(int size) {
-        tos += size;
-    }
-
-    private void decrementTos(int size) {
-        assert tos - size >= stackTos();
-        tos -= size;
-    }
-
-    private int tosDouble(int offset) {
-        assert offset >= 0;
-        return tos - DOUBLE - (offset * DOUBLE);
-    }
-
-    private int tosSingle(int offset) {
-        assert offset >= 0;
-        return tos - SINGLE - offset;
-    }
-
-    public int getStackTop() {
-        return tos;
-    }
-
-    public void pushVoid(int count) {
-        incrementTos(count * SINGLE);
-    }
-
-    public void popVoid(int count) {
-        decrementTos(count * SINGLE);
-    }
-
-    public ConstantPool getConstantPool() {
-        return getMethod().getConstantPool();
-    }
-
-    private void setMethod(ResolvedJavaMethod method) {
-        setObject(METHOD_FRAME_SLOT, method);
-    }
-
-    public ResolvedJavaMethod getMethod() {
-        return (ResolvedJavaMethod) getObject(METHOD_FRAME_SLOT);
-    }
-
-    public void setBCI(int bci) {
-        setInt(BCI_FRAME_SLOT, bci);
-    }
-
-    public int getBCI() {
-        return getInt(BCI_FRAME_SLOT);
-    }
-
-    public void pushTo(InterpreterFrame childFrame, int argumentSlots) {
-        System.arraycopy(locals, tos - argumentSlots, childFrame.locals, InterpreterFrame.MIN_FRAME_SIZE, argumentSlots);
-
-        System.arraycopy(primitiveLocals, tos - argumentSlots, childFrame.primitiveLocals, InterpreterFrame.MIN_FRAME_SIZE, argumentSlots);
-        popVoid(argumentSlots);
-    }
-
-    public InterpreterFrame getParentFrame() {
-        return (InterpreterFrame) getObject(PARENT_FRAME_SLOT);
-    }
-
-    public void dispose() {
-        // Clear out references in locals array.
-        Arrays.fill(locals, null);
-    }
-
-    @Override
-    public String toString() {
-        ResolvedJavaMethod method = getMethod();
-        StringBuilder b = new StringBuilder(getMethod().asStackTraceElement(getBCI()).toString());
-        for (int i = 0; i < tos; i++) {
-            Object object = getObject(tosSingle(i));
-            long primitive = getLong(tosSingle(i));
-
-            String objectString = null;
-            if (object != null) {
-                objectString = object.getClass().getSimpleName() + "@" + Integer.toHexString(object.hashCode());
-            }
-            String primitiveString = "0x" + Long.toHexString(primitive).toUpperCase();
-            String typeString;
-
-            int index = tosSingle(i);
-            if (index == METHOD_FRAME_SLOT) {
-                typeString = "method";
-            } else if (index == BCI_FRAME_SLOT) {
-                typeString = "bci";
-            } else if (index == PARENT_FRAME_SLOT) {
-                typeString = "parent";
-            } else if (index < BASE_LENGTH + method.getMaxLocals()) {
-                typeString = "var " + (index - BASE_LENGTH);
-            } else {
-                typeString = "local";
-            }
-            b.append(String.format("%n [%d] %7s Primitive: %10s Object: %s", index, typeString, primitiveString, objectString));
-        }
-        if (getParentFrame() != null) {
-            b.append("\n").append(getParentFrame().toString());
-        }
-        return b.toString();
-    }
-
-    public void popStack() {
-        // TODO(chumer): prevent popping local variables.
-        popVoid(tos - stackTos());
-    }
-
-}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Feb 11 10:41:29 2013 +0100
@@ -708,7 +708,8 @@
         if (type instanceof ResolvedJavaType) {
             ResolvedJavaType resolvedType = (ResolvedJavaType) type;
             InstanceOfNode instanceOfNode = new InstanceOfNode((ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType));
-            frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode))));
+            ConditionalNode conditional = currentGraph.unique(new ConditionalNode(currentGraph.unique(instanceOfNode), ConstantNode.forInt(1, currentGraph), ConstantNode.forInt(0, currentGraph)));
+            frameState.ipush(append(conditional));
         } else {
             BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode());
             DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved));
@@ -765,7 +766,7 @@
     private void genNewPrimitiveArray(int typeCode) {
         Class<?> clazz = arrayTypeCodeToClass(typeCode);
         ResolvedJavaType elementType = runtime.lookupJavaType(clazz);
-        NewPrimitiveArrayNode nta = currentGraph.add(new NewPrimitiveArrayNode(elementType, frameState.ipop(), true, false));
+        NewArrayNode nta = currentGraph.add(new NewArrayNode(elementType, frameState.ipop(), true, false));
         frameState.apush(append(nta));
     }
 
@@ -773,7 +774,7 @@
         JavaType type = lookupType(cpi, ANEWARRAY);
         ValueNode length = frameState.ipop();
         if (type instanceof ResolvedJavaType) {
-            NewArrayNode n = currentGraph.add(new NewObjectArrayNode((ResolvedJavaType) type, length, true, false));
+            NewArrayNode n = currentGraph.add(new NewArrayNode((ResolvedJavaType) type, length, true, false));
             frameState.apush(append(n));
         } else {
             append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
@@ -1143,6 +1144,19 @@
         return true;
     }
 
+    /**
+     * Helper function that sums up the probabilities of all keys that lead to a specific successor.
+     * 
+     * @return an array of size successorCount with the accumulated probability for each successor.
+     */
+    private static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) {
+        double[] probability = new double[successorCount];
+        for (int i = 0; i < keySuccessors.length; i++) {
+            probability[keySuccessors[i]] += keyProbabilities[i];
+        }
+        return probability;
+    }
+
     private void genSwitch(BytecodeSwitch bs) {
         int bci = bci();
         ValueNode value = frameState.ipop();
@@ -1185,7 +1199,7 @@
             }
         }
 
-        double[] successorProbabilities = IntegerSwitchNode.successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities);
+        double[] successorProbabilities = successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities);
         IntegerSwitchNode switchNode = currentGraph.add(new IntegerSwitchNode(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors));
         for (int i = 0; i < actualSuccessors.size(); i++) {
             switchNode.setBlockSuccessor(i, createBlockTarget(successorProbabilities[i], actualSuccessors.get(i), frameState));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java	Mon Feb 11 10:41:29 2013 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.amd64;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.asm.*;
+
+//@formatter:off
+public class AMD64TestOp extends AMD64LIRInstruction {
+
+    @Use({REG}) protected Value x;
+    @Use({REG, STACK, CONST}) protected Value y;
+
+    public AMD64TestOp(Value x, Value y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        emit(tasm, masm, x, y);
+    }
+
+    @Override
+    protected void verify() {
+        super.verify();
+        assert (x.getKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) || (x.getKind() == Kind.Long && y.getKind() == Kind.Long) : x + " " + y;
+    }
+
+    public static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value x, Value y) {
+        if (isRegister(y)) {
+            switch (x.getKind()) {
+                case Int: masm.testl(asIntReg(x), asIntReg(y)); break;
+                case Long: masm.testq(asLongReg(x), asLongReg(y)); break;
+                default: throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(y)) {
+            switch (x.getKind()) {
+                case Int: masm.testl(asIntReg(x), tasm.asIntConst(y)); break;
+                case Long: masm.testq(asLongReg(x), tasm.asIntConst(y)); break;
+                default: throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            switch (x.getKind()) {
+                case Int: masm.testl(asIntReg(x), tasm.asIntAddr(y)); break;
+                case Long: masm.testq(asLongReg(x), tasm.asLongAddr(y)); break;
+                default: throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCLIRInstruction.java	Mon Feb 11 10:41:29 2013 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.sparc;
+
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method.
+ */
+public abstract class SPARCLIRInstruction extends LIRInstruction {
+
+    @Override
+    public final void emitCode(TargetMethodAssembler tasm) {
+        emitCode(tasm, (SPARCAssembler) tasm.asm);
+    }
+
+    public abstract void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm);
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -191,7 +191,7 @@
                             return false;
                         }
                         if (trueValue.isConstant() && falseValue.isConstant()) {
-                            MaterializeNode materialize = MaterializeNode.create(condition(), trueValue, falseValue);
+                            ConditionalNode materialize = graph().unique(new ConditionalNode(condition(), trueValue, falseValue));
                             ((StructuredGraph) graph()).replaceFloating(singlePhi, materialize);
                             removeEmptyIf(tool);
                             return true;
@@ -323,6 +323,7 @@
             }
         }
         assert !ends.hasNext();
+        assert falseEnds.size() + trueEnds.size() == xs.length;
 
         connectEnds(falseEnds, phiValues, oldFalseSuccessor, merge, tool);
         connectEnds(trueEnds, phiValues, oldTrueSuccessor, merge, tool);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes;
-
-import static com.oracle.graal.nodes.calc.CompareNode.*;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
-
-public final class MaterializeNode extends ConditionalNode {
-
-    private MaterializeNode(Condition condition, ValueNode x, ValueNode y) {
-        this(createCompareNode(condition, x, y), ConstantNode.forInt(1, x.graph()), ConstantNode.forInt(0, x.graph()));
-    }
-
-    private MaterializeNode(BooleanNode condition, ValueNode trueValue, ValueNode falseValue) {
-        super(condition, trueValue, falseValue);
-    }
-
-    private MaterializeNode(ValueNode type, ValueNode object) {
-        super(type.graph().add(new InstanceOfDynamicNode(type, object)), ConstantNode.forInt(1, type.graph()), ConstantNode.forInt(0, type.graph()));
-    }
-
-    public static MaterializeNode create(BooleanNode condition, ValueNode trueValue, ValueNode falseValue) {
-        Graph graph = condition.graph();
-        MaterializeNode result = new MaterializeNode(condition, trueValue, falseValue);
-        return graph.unique(result);
-
-    }
-
-    public static MaterializeNode create(BooleanNode condition) {
-        return create(condition, ConstantNode.forInt(1, condition.graph()), ConstantNode.forInt(0, condition.graph()));
-    }
-
-    @NodeIntrinsic
-    public static native boolean materialize(@ConstantNodeParameter Condition condition, int x, int y);
-
-    @NodeIntrinsic
-    public static native boolean materialize(@ConstantNodeParameter Condition condition, long x, long y);
-
-    @NodeIntrinsic
-    public static native boolean isInstance(Class mirror, Object object);
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -22,15 +22,18 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import static com.oracle.graal.nodes.calc.CompareNode.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
  * The {@code ConditionalNode} class represents a comparison that yields one of two values. Note
  * that these nodes are not built directly from the bytecode but are introduced by canonicalization.
  */
-public class ConditionalNode extends BinaryNode implements Canonicalizable, LIRLowerable, Negatable {
+public final class ConditionalNode extends BinaryNode implements Canonicalizable, LIRLowerable, Negatable {
 
     @Input private BooleanNode condition;
 
@@ -44,6 +47,11 @@
         this.condition = condition;
     }
 
+    @Override
+    public boolean inferStamp() {
+        return updateStamp(x().stamp().meet(y().stamp()));
+    }
+
     public ValueNode trueValue() {
         return x();
     }
@@ -91,4 +99,21 @@
         ((StructuredGraph) graph()).replaceFloating(this, replacement);
         return replacement;
     }
+
+    private ConditionalNode(Condition condition, ValueNode x, ValueNode y) {
+        this(createCompareNode(condition, x, y), ConstantNode.forInt(1, x.graph()), ConstantNode.forInt(0, x.graph()));
+    }
+
+    private ConditionalNode(ValueNode type, ValueNode object) {
+        this(type.graph().add(new InstanceOfDynamicNode(type, object)), ConstantNode.forInt(1, type.graph()), ConstantNode.forInt(0, type.graph()));
+    }
+
+    @NodeIntrinsic
+    public static native boolean materializeCondition(@ConstantNodeParameter Condition condition, int x, int y);
+
+    @NodeIntrinsic
+    public static native boolean materializeCondition(@ConstantNodeParameter Condition condition, long x, long y);
+
+    @NodeIntrinsic
+    public static native boolean materializeIsInstance(Class mirror, Object object);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -74,6 +74,12 @@
         } else if (x().integerStamp().alwaysDistinct(y().integerStamp())) {
             return ConstantNode.forBoolean(false, graph());
         }
+
+        if (x() instanceof AndNode && y().isConstant() && y().asConstant().asLong() == 0) {
+            return graph().unique(new IntegerTestNode(((AndNode) x()).x(), ((AndNode) x()).y()));
+        } else if (y() instanceof AndNode && x().isConstant() && x().asConstant().asLong() == 0) {
+            return graph().unique(new IntegerTestNode(((AndNode) y()).x(), ((AndNode) y()).y()));
+        }
         return super.canonical(tool);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.calc;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public class IntegerTestNode extends BooleanNode implements Canonicalizable, LIRLowerable {
+
+    @Input private ValueNode x;
+    @Input private ValueNode y;
+
+    public ValueNode x() {
+        return x;
+    }
+
+    public ValueNode y() {
+        return y;
+    }
+
+    /**
+     * Constructs a new Test instruction.
+     * 
+     * @param x the instruction producing the first input to the instruction
+     * @param y the instruction that produces the second input to this instruction
+     */
+    public IntegerTestNode(ValueNode x, ValueNode y) {
+        super(StampFactory.condition());
+        assert (x == null && y == null) || x.kind() == y.kind();
+        this.x = x;
+        this.y = y;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool gen) {
+    }
+
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (x().isConstant() && y().isConstant()) {
+            return ConstantNode.forBoolean((x().asConstant().asLong() & y().asConstant().asLong()) == 0, graph());
+        }
+        if ((x().integerStamp().mask() & y().integerStamp().mask()) == 0) {
+            return ConstantNode.forBoolean(true, graph());
+        }
+        return this;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -61,8 +61,8 @@
             lessComp = graph.unique(new IntegerLessThanNode(x(), y()));
         }
 
-        MaterializeNode equalValue = MaterializeNode.create(equalComp, ConstantNode.forInt(0, graph), ConstantNode.forInt(1, graph));
-        MaterializeNode value = MaterializeNode.create(lessComp, ConstantNode.forInt(-1, graph), equalValue);
+        ConditionalNode equalValue = graph.unique(new ConditionalNode(equalComp, ConstantNode.forInt(0, graph), ConstantNode.forInt(1, graph)));
+        ConditionalNode value = graph.unique(new ConditionalNode(lessComp, ConstantNode.forInt(-1, graph), equalValue));
 
         graph.replaceFloating(this, value);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -49,7 +49,7 @@
      * @param keySuccessors the successor index for each key
      */
     public IntegerSwitchNode(ValueNode value, BeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
-        super(value, successors, successorProbabilites(successors.length, keySuccessors, keyProbabilities), keySuccessors, keyProbabilities);
+        super(value, successors, keySuccessors, keyProbabilities);
         assert keySuccessors.length == keys.length + 1;
         assert keySuccessors.length == keyProbabilities.length;
         this.keys = keys;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -35,7 +35,6 @@
 public abstract class SwitchNode extends ControlSplitNode {
 
     @Successor protected final NodeSuccessorList<BeginNode> successors;
-    protected double[] successorProbabilities;
     @Input private ValueNode value;
     private double[] keyProbabilities;
     private int[] keySuccessors;
@@ -46,9 +45,8 @@
      * @param value the instruction that provides the value to be switched over
      * @param successors the list of successors of this switch
      */
-    public SwitchNode(ValueNode value, BeginNode[] successors, double[] successorProbabilities, int[] keySuccessors, double[] keyProbabilities) {
+    public SwitchNode(ValueNode value, BeginNode[] successors, int[] keySuccessors, double[] keyProbabilities) {
         super(StampFactory.forVoid());
-        this.successorProbabilities = successorProbabilities;
         assert keySuccessors.length == keyProbabilities.length;
         this.successors = new NodeSuccessorList<>(this, successors);
         this.value = value;
@@ -59,9 +57,9 @@
     @Override
     public double probability(BeginNode successor) {
         double sum = 0;
-        for (int i = 0; i < successors.size(); i++) {
-            if (successors.get(i) == successor) {
-                sum += successorProbabilities[i];
+        for (int i = 0; i < keySuccessors.length; i++) {
+            if (successors.get(keySuccessors[i]) == successor) {
+                sum += keyProbabilities[i];
             }
         }
         return sum;
@@ -133,23 +131,9 @@
         return defaultSuccessorIndex() == -1 ? null : successors.get(defaultSuccessorIndex());
     }
 
-    /**
-     * Helper function that sums up the probabilities of all keys that lead to a specific successor.
-     * 
-     * @return an array of size successorCount with the accumulated probability for each successor.
-     */
-    public static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) {
-        double[] probability = new double[successorCount];
-        for (int i = 0; i < keySuccessors.length; i++) {
-            probability[keySuccessors[i]] += keyProbabilities[i];
-        }
-        return probability;
-    }
-
     @Override
     public SwitchNode clone(Graph into) {
         SwitchNode newSwitch = (SwitchNode) super.clone(into);
-        newSwitch.successorProbabilities = Arrays.copyOf(successorProbabilities, successorProbabilities.length);
         newSwitch.keyProbabilities = Arrays.copyOf(keyProbabilities, keyProbabilities.length);
         newSwitch.keySuccessors = Arrays.copyOf(keySuccessors, keySuccessors.length);
         return newSwitch;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -131,10 +131,6 @@
         return this;
     }
 
-    public JavaType returnType() {
-        return returnType;
-    }
-
     @Override
     public Stamp returnStamp() {
         Kind returnKind = targetMethod.getSignature().getReturnKind();
@@ -145,6 +141,10 @@
         }
     }
 
+    public JavaType returnType() {
+        return returnType;
+    }
+
     @Override
     public String targetName() {
         if (targetMethod() == null) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -23,15 +23,16 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
 
 /**
- * The {@code NewArrayNode} class is the base of all instructions that allocate arrays.
+ * The {@code NewArrayNode} is used for all 1-dimensional array allocations.
  */
-public abstract class NewArrayNode extends FixedWithNextNode implements Canonicalizable, Lowerable, VirtualizableAllocation, ArrayLengthProvider {
+public class NewArrayNode extends FixedWithNextNode implements Canonicalizable, Lowerable, VirtualizableAllocation, ArrayLengthProvider, Node.IterableNodeType {
 
     @Input private ValueNode length;
     private final ResolvedJavaType elementType;
@@ -53,7 +54,7 @@
      * @param fillContents determines whether the array elements should be initialized to zero/null.
      * @param locked determines whether the array should be locked immediately.
      */
-    protected NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents, boolean locked) {
+    public NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents, boolean locked) {
         super(StampFactory.exactNonNull(elementType.getArrayClass()));
         this.length = length;
         this.elementType = elementType;
@@ -123,7 +124,7 @@
                 for (int i = 0; i < constantLength; i++) {
                     state[i] = defaultForKind;
                 }
-                VirtualObjectNode virtualObject = new VirtualArrayNode(tool.getNextVirtualId(), elementType, constantLength);
+                VirtualObjectNode virtualObject = new VirtualArrayNode(elementType, constantLength);
                 tool.createVirtualObject(virtualObject, state, 0);
                 tool.replaceWithVirtual(virtualObject);
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -100,7 +100,7 @@
             for (int i = 0; i < state.length; i++) {
                 state[i] = ConstantNode.defaultForKind(fields[i].getType().getKind(), graph());
             }
-            VirtualObjectNode virtualObject = new VirtualInstanceNode(tool.getNextVirtualId(), instanceClass(), fields);
+            VirtualObjectNode virtualObject = new VirtualInstanceNode(instanceClass(), fields);
             tool.createVirtualObject(virtualObject, state, 0);
             tool.replaceWithVirtual(virtualObject);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewObjectArrayNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.java;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-
-/**
- * The {@code NewObjectArrayNode} represents an allocation of an object array.
- */
-@NodeInfo(nameTemplate = "NewArray {p#elementType}")
-public final class NewObjectArrayNode extends NewArrayNode implements Node.IterableNodeType {
-
-    /**
-     * Constructs a new NewObjectArrayNode.
-     * 
-     * @param elementClass the class of elements in this array
-     * @param length the node producing the length of the array
-     * @param fillContents determines whether the array elements should be initialized to null.
-     * @param locked determines whether the array should be locked immediately.
-     */
-    public NewObjectArrayNode(ResolvedJavaType elementClass, ValueNode length, boolean fillContents, boolean locked) {
-        super(elementClass, length, fillContents, locked);
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewPrimitiveArrayNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.java;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-
-/**
- * The {@code NewPrimitiveArrayNode} class definition.
- */
-@NodeInfo(nameTemplate = "NewArray {p#elementType}")
-public final class NewPrimitiveArrayNode extends NewArrayNode implements Node.IterableNodeType {
-
-    /**
-     * Constructs a new NewPrimitiveArrayNode.
-     * 
-     * @param elementType the type of elements in this array
-     * @param length the node producing the length of the array
-     * @param fillContents determines whether the array elements should be initialized to zero.
-     * @param locked determines whether the array should be locked immediately.
-     */
-    public NewPrimitiveArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents, boolean locked) {
-        super(elementType, length, fillContents, locked);
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -44,14 +44,14 @@
      * Constructs a type switch instruction. The keyProbabilities array contain key.length + 1
      * entries. The last entry in every array describes the default case.
      * 
-     * @param value the instruction producing the value being switched on
+     * @param value the instruction producing the value being switched on, the object hub
      * @param successors the list of successors
      * @param keys the list of types
      * @param keyProbabilities the probabilities of the keys
      * @param keySuccessors the successor index for each key
      */
-    public TypeSwitchNode(ValueNode value, BeginNode[] successors, double[] successorProbabilities, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) {
-        super(value, successors, successorProbabilities, keySuccessors, keyProbabilities);
+    public TypeSwitchNode(ValueNode value, BeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) {
+        super(value, successors, keySuccessors, keyProbabilities);
         assert successors.length <= keys.length + 1;
         assert keySuccessors.length == keyProbabilities.length;
         this.keys = keys;
@@ -63,8 +63,12 @@
     }
 
     @Override
-    public Constant keyAt(int i) {
-        return keys[i].getEncoding(Representation.ObjectHub);
+    public Constant keyAt(int index) {
+        return keys[index].getEncoding(Representation.ObjectHub);
+    }
+
+    public ResolvedJavaType typeAt(int index) {
+        return keys[index];
     }
 
     @Override
@@ -134,8 +138,6 @@
                         }
                     }
 
-                    double[] newSuccessorProbabilities = successorProbabilites(newSuccessors.size(), newKeySuccessors, newKeyProbabilities);
-
                     for (int i = 0; i < blockSuccessorCount(); i++) {
                         BeginNode successor = blockSuccessor(i);
                         if (!newSuccessors.contains(successor)) {
@@ -145,7 +147,7 @@
                     }
 
                     BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]);
-                    TypeSwitchNode newSwitch = graph().add(new TypeSwitchNode(value(), successorsArray, newSuccessorProbabilities, newKeys, newKeyProbabilities, newKeySuccessors));
+                    TypeSwitchNode newSwitch = graph().add(new TypeSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors));
                     ((FixedWithNextNode) predecessor()).setNext(newSwitch);
                     GraphUtil.killWithUnusedFloatingInputs(this);
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java	Mon Feb 11 10:41:29 2013 +0100
@@ -50,11 +50,6 @@
      */
     int getMaximumEntryCount();
 
-    /**
-     * @return the next id for virtual objects (can be used for the VirtualObject constructor).
-     */
-    int getNextVirtualId();
-
     // methods working on virtualized/materialized objects
 
     /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Mon Feb 11 10:41:29 2013 +0100
@@ -232,7 +232,7 @@
         RuntimeException exception = new RuntimeException(cause.getMessage(), cause) {
 
             @Override
-            public synchronized Throwable fillInStackTrace() {
+            public final synchronized Throwable fillInStackTrace() {
                 setStackTrace(elements);
                 return this;
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -33,8 +33,7 @@
     private final ResolvedJavaType type;
     private final Kind kind;
 
-    public BoxedVirtualObjectNode(int virtualId, ResolvedJavaType type, Kind kind, ValueNode unboxedValue) {
-        super(virtualId);
+    public BoxedVirtualObjectNode(ResolvedJavaType type, Kind kind, ValueNode unboxedValue) {
         this.type = type;
         this.kind = kind;
         this.unboxedValue = unboxedValue;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -34,8 +34,7 @@
     private final ResolvedJavaType componentType;
     private final int length;
 
-    public VirtualArrayNode(long virtualId, ResolvedJavaType componentType, int length) {
-        super(virtualId);
+    public VirtualArrayNode(ResolvedJavaType componentType, int length) {
         this.componentType = componentType;
         this.length = length;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -34,8 +34,7 @@
     private final ResolvedJavaField[] fields;
     private final HashMap<ResolvedJavaField, Integer> fieldMap = new HashMap<>();
 
-    public VirtualInstanceNode(long virtualId, ResolvedJavaType type, ResolvedJavaField[] fields) {
-        super(virtualId);
+    public VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) {
         this.type = type;
         this.fields = fields;
         for (int i = 0; i < fields.length; i++) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -25,28 +25,20 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(nameTemplate = "VirtualObject {p#type}")
-public abstract class VirtualObjectNode extends FloatingNode implements LIRLowerable {
-
-    private final long virtualId;
+public abstract class VirtualObjectNode extends ValueNode implements LIRLowerable {
 
-    public VirtualObjectNode(long virtualId) {
+    public VirtualObjectNode() {
         super(StampFactory.virtual());
-        this.virtualId = virtualId;
     }
 
     public abstract ResolvedJavaType type();
 
     public abstract int entryCount();
 
-    public long virtualId() {
-        return virtualId;
-    }
-
     @Override
     public void generate(LIRGeneratorTool gen) {
         // nothing to do...
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/BoxingEliminationPhase.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/BoxingEliminationPhase.java	Mon Feb 11 10:41:29 2013 +0100
@@ -38,7 +38,6 @@
 public class BoxingEliminationPhase extends Phase {
 
     private final MetaAccessProvider metaAccess;
-    private int virtualIds = Integer.MIN_VALUE;
 
     public BoxingEliminationPhase(MetaAccessProvider metaAccess) {
         this.metaAccess = metaAccess;
@@ -113,7 +112,7 @@
         }
     }
 
-    private void tryEliminate(BoxNode boxNode) {
+    private static void tryEliminate(BoxNode boxNode) {
 
         assert boxNode.objectStamp().isExactType();
         virtualizeUsages(boxNode, boxNode.source(), boxNode.objectStamp().type(), boxNode.getSourceKind());
@@ -130,12 +129,12 @@
         ((StructuredGraph) boxNode.graph()).removeFixed(boxNode);
     }
 
-    private void virtualizeUsages(ValueNode boxNode, ValueNode replacement, ResolvedJavaType exactType, Kind sourceKind) {
+    private static void virtualizeUsages(ValueNode boxNode, ValueNode replacement, ResolvedJavaType exactType, Kind sourceKind) {
         ValueNode virtualValueNode = null;
         VirtualObjectNode virtualObjectNode = null;
         for (Node n : boxNode.usages().filter(NodePredicates.isA(VirtualState.class)).snapshot()) {
             if (virtualValueNode == null) {
-                virtualObjectNode = n.graph().unique(new BoxedVirtualObjectNode(virtualIds++, exactType, sourceKind, replacement));
+                virtualObjectNode = n.graph().unique(new BoxedVirtualObjectNode(exactType, sourceKind, replacement));
             }
             n.replaceFirstInput(boxNode, virtualObjectNode);
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java	Mon Feb 11 10:41:29 2013 +0100
@@ -60,63 +60,9 @@
         computeLoopFactors();
         Debug.dump(graph, "After computeLoopFactors");
         new PropagateLoopFrequency(graph.start()).apply();
-
-        if (GraalOptions.LoopFrequencyPropagationPolicy < 0) {
-            ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false);
-            BitSet visitedBlocks = new BitSet(cfg.getBlocks().length);
-            for (Loop loop : cfg.getLoops()) {
-                if (loop.parent == null) {
-                    correctLoopFrequencies(loop, 1, visitedBlocks);
-                }
-            }
-        }
-
         new ComputeInliningRelevanceIterator(graph).apply();
     }
 
-    private void correctLoopFrequencies(Loop loop, double parentFrequency, BitSet visitedBlocks) {
-        LoopBeginNode loopBegin = ((LoopBeginNode) loop.header.getBeginNode());
-        double frequency = parentFrequency * loopBegin.loopFrequency();
-        if (frequency < 1) {
-            frequency = 1;
-        }
-        for (Loop child : loop.children) {
-            correctLoopFrequencies(child, frequency, visitedBlocks);
-        }
-
-        double factor = getCorrectionFactor(loopBegin.probability(), frequency);
-        for (Block block : loop.blocks) {
-            int blockId = block.getId();
-            if (!visitedBlocks.get(blockId)) {
-                visitedBlocks.set(blockId);
-
-                FixedNode node = block.getBeginNode();
-                while (node != block.getEndNode()) {
-                    node.setProbability(node.probability() * factor);
-                    node = ((FixedWithNextNode) node).next();
-                }
-                node.setProbability(node.probability() * factor);
-            }
-        }
-    }
-
-    private static double getCorrectionFactor(double probability, double frequency) {
-        switch (GraalOptions.LoopFrequencyPropagationPolicy) {
-            case -1:
-                return 1 / frequency;
-            case -2:
-                return (1 / frequency) * (Math.log(Math.E + frequency) - 1);
-            case -3:
-                double originalProbability = probability / frequency;
-                assert isRelativeProbability(originalProbability);
-                return (1 / frequency) * Math.max(1, Math.pow(originalProbability, 1.5) * Math.log10(frequency));
-            case -4:
-                return 1 / probability;
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
     private void computeLoopFactors() {
         for (LoopInfo info : loopInfos) {
             double frequency = info.loopFrequency();
@@ -330,124 +276,184 @@
 
     private class PropagateLoopFrequency extends PostOrderNodeIterator<LoopCount> {
 
-        private final FrequencyPropagationPolicy policy;
-
         public PropagateLoopFrequency(FixedNode start) {
             super(start, new LoopCount(1d));
-            this.policy = createFrequencyPropagationPolicy();
         }
 
         @Override
         protected void node(FixedNode node) {
-            node.setProbability(policy.compute(node.probability(), state.count));
+            node.setProbability(node.probability() * state.count);
         }
 
     }
 
-    private static FrequencyPropagationPolicy createFrequencyPropagationPolicy() {
-        switch (GraalOptions.LoopFrequencyPropagationPolicy) {
-            case -4:
-            case -3:
-            case -2:
-            case -1:
-            case 0:
-                return new FullFrequencyPropagation();
-            case 1:
-                return new NoFrequencyPropagation();
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
-    private interface FrequencyPropagationPolicy {
-
-        double compute(double probability, double frequency);
-    }
-
-    private static class FullFrequencyPropagation implements FrequencyPropagationPolicy {
-
-        @Override
-        public double compute(double probability, double frequency) {
-            return probability * frequency;
-        }
-    }
-
-    private static class NoFrequencyPropagation implements FrequencyPropagationPolicy {
-
-        @Override
-        public double compute(double probability, double frequency) {
-            return probability;
-        }
-    }
-
     private static class ComputeInliningRelevanceIterator extends ScopedPostOrderNodeIterator {
 
-        private final HashMap<FixedNode, Double> lowestPathProbabilities;
+        private final HashMap<FixedNode, Scope> scopes;
         private double currentProbability;
+        private double parentRelevance;
 
         public ComputeInliningRelevanceIterator(StructuredGraph graph) {
             super(graph);
-            this.lowestPathProbabilities = computeLowestPathProbabilities(graph);
+            this.scopes = computeLowestPathProbabilities(computeScopeInformation(graph));
         }
 
         @Override
         protected void initializeScope() {
-            currentProbability = lowestPathProbabilities.get(currentScope);
+            Scope scope = scopes.get(currentScopeStart);
+            parentRelevance = getParentScopeRelevance(scope);
+            currentProbability = scope.minPathProbability;
+        }
+
+        private static double getParentScopeRelevance(Scope scope) {
+            if (scope.start instanceof LoopBeginNode) {
+                assert scope.parent != null;
+                double parentProbability = 0;
+                for (EndNode end : ((LoopBeginNode) scope.start).forwardEnds()) {
+                    parentProbability += end.probability();
+                }
+                return parentProbability / scope.parent.minPathProbability;
+            } else {
+                assert scope.parent == null;
+                return 1.0;
+            }
         }
 
         @Override
         protected void invoke(Invoke invoke) {
             assert !Double.isNaN(invoke.probability());
-            invoke.setInliningRelevance(invoke.probability() / currentProbability);
+            invoke.setInliningRelevance((invoke.probability() / currentProbability) * Math.min(1.0, parentRelevance));
+            assert !Double.isNaN(invoke.inliningRelevance());
         }
 
-        private HashMap<FixedNode, Double> computeLowestPathProbabilities(StructuredGraph graph) {
-            HashMap<FixedNode, Double> result = new HashMap<>();
-            Deque<FixedNode> scopes = getScopes(graph);
+        private static Scope[] computeScopeInformation(StructuredGraph graph) {
+            ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false);
+
+            Loop[] loops = cfg.getLoops();
+            HashMap<Loop, Scope> processedScopes = new HashMap<>();
+            Scope[] scopes = new Scope[loops.length + 1];
+            Scope methodScope = new Scope(graph.start(), null);
+            processedScopes.put(null, methodScope);
+
+            scopes[0] = methodScope;
+            for (int i = 0; i < loops.length; i++) {
+                scopes[i + 1] = createScope(loops[i], processedScopes);
+            }
+
+            return scopes;
+        }
 
-            while (!scopes.isEmpty()) {
-                FixedNode scopeBegin = scopes.pop();
-                double probability = computeLowestPathProbability(scopeBegin);
-                result.put(scopeBegin, probability);
+        private static Scope createScope(Loop loop, HashMap<Loop, Scope> processedLoops) {
+            Scope parent = processedLoops.get(loop.parent);
+            if (parent == null) {
+                parent = createScope(loop, processedLoops);
+            }
+            Scope result = new Scope(loop.loopBegin(), parent);
+            processedLoops.put(loop, result);
+            return result;
+        }
+
+        private static HashMap<FixedNode, Scope> computeLowestPathProbabilities(Scope[] scopes) {
+            HashMap<FixedNode, Scope> result = new HashMap<>();
+
+            for (Scope scope : scopes) {
+                double lowestPathProbability = computeLowestPathProbability(scope);
+                scope.minPathProbability = Math.max(EPSILON, lowestPathProbability);
+                result.put(scope.start, scope);
             }
 
             return result;
         }
 
-        private static double computeLowestPathProbability(FixedNode scopeStart) {
+        private static double computeLowestPathProbability(Scope scope) {
+            FixedNode scopeStart = scope.start;
+            ArrayList<FixedNode> pathBeginNodes = new ArrayList<>();
+            pathBeginNodes.add(scopeStart);
             double minPathProbability = scopeStart.probability();
-            Node current = scopeStart;
+            boolean isLoopScope = scopeStart instanceof LoopBeginNode;
 
-            while (current != null) {
-                if (current.successors().count() > 1) {
-                    assert current instanceof ControlSplitNode;
-                    ControlSplitNode controlSplit = (ControlSplitNode) current;
-                    current = getMaxProbabilitySux(controlSplit);
-                    if (((FixedNode) current).probability() < minPathProbability) {
-                        minPathProbability = ((FixedNode) current).probability();
+            do {
+                Node current = pathBeginNodes.remove(pathBeginNodes.size() - 1);
+                do {
+                    if (isLoopScope && current instanceof LoopExitNode && ((LoopBeginNode) scopeStart).loopExits().contains((LoopExitNode) current)) {
+                        return minPathProbability;
+                    } else if (current instanceof LoopBeginNode && current != scopeStart) {
+                        current = getMaxProbabilityLoopExit((LoopBeginNode) current, pathBeginNodes);
+                        minPathProbability = getMinPathProbability((FixedNode) current, minPathProbability);
+                    } else if (current instanceof ControlSplitNode) {
+                        current = getMaxProbabilitySux((ControlSplitNode) current, pathBeginNodes);
+                        minPathProbability = getMinPathProbability((FixedNode) current, minPathProbability);
+                    } else {
+                        assert current.successors().count() <= 1;
+                        current = current.successors().first();
                     }
-                } else {
-                    current = current.successors().first();
-                }
-            }
+                } while (current != null);
+            } while (!pathBeginNodes.isEmpty());
 
             return minPathProbability;
         }
 
-        private static Node getMaxProbabilitySux(ControlSplitNode controlSplit) {
+        private static double getMinPathProbability(FixedNode current, double minPathProbability) {
+            if (current != null && current.probability() < minPathProbability) {
+                return current.probability();
+            }
+            return minPathProbability;
+        }
+
+        private static Node getMaxProbabilitySux(ControlSplitNode controlSplit, ArrayList<FixedNode> pathBeginNodes) {
             Node maxSux = null;
             double maxProbability = 0.0;
+            int pathBeginCount = pathBeginNodes.size();
 
-            // TODO: process recursively if we have multiple successors with same probability
             for (Node sux : controlSplit.successors()) {
                 double probability = controlSplit.probability((BeginNode) sux);
                 if (probability > maxProbability) {
                     maxProbability = probability;
                     maxSux = sux;
+                    truncate(pathBeginNodes, pathBeginCount);
+                } else if (probability == maxProbability) {
+                    pathBeginNodes.add((FixedNode) sux);
                 }
             }
 
             return maxSux;
         }
+
+        private static Node getMaxProbabilityLoopExit(LoopBeginNode loopBegin, ArrayList<FixedNode> pathBeginNodes) {
+            Node maxSux = null;
+            double maxProbability = 0.0;
+            int pathBeginCount = pathBeginNodes.size();
+
+            for (LoopExitNode sux : loopBegin.loopExits()) {
+                double probability = sux.probability();
+                if (probability > maxProbability) {
+                    maxProbability = probability;
+                    maxSux = sux;
+                    truncate(pathBeginNodes, pathBeginCount);
+                } else if (probability == maxProbability) {
+                    pathBeginNodes.add(sux);
+                }
+            }
+
+            return maxSux;
+        }
+
+        public static void truncate(ArrayList<FixedNode> pathBeginNodes, int pathBeginCount) {
+            for (int i = pathBeginNodes.size() - pathBeginCount; i > 0; i--) {
+                pathBeginNodes.remove(pathBeginNodes.size() - 1);
+            }
+        }
+    }
+
+    private static class Scope {
+
+        public final FixedNode start;
+        public final Scope parent;
+        public double minPathProbability;
+
+        public Scope(FixedNode start, Scope parent) {
+            this.start = start;
+            this.parent = parent;
+        }
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Feb 11 10:41:29 2013 +0100
@@ -30,6 +30,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
@@ -38,16 +39,24 @@
 
 public class ConditionalEliminationPhase extends Phase {
 
-    private static final DebugMetric metricInstanceOfRegistered = Debug.metric("InstanceOfRegistered");
-    private static final DebugMetric metricNullCheckRegistered = Debug.metric("NullCheckRegistered");
+    private static final DebugMetric metricConditionRegistered = Debug.metric("ConditionRegistered");
+    private static final DebugMetric metricTypeRegistered = Debug.metric("TypeRegistered");
+    private static final DebugMetric metricNullnessRegistered = Debug.metric("NullnessRegistered");
+    private static final DebugMetric metricObjectEqualsRegistered = Debug.metric("ObjectEqualsRegistered");
     private static final DebugMetric metricCheckCastRemoved = Debug.metric("CheckCastRemoved");
     private static final DebugMetric metricInstanceOfRemoved = Debug.metric("InstanceOfRemoved");
     private static final DebugMetric metricNullCheckRemoved = Debug.metric("NullCheckRemoved");
-    private static final DebugMetric metricNullCheckGuardRemoved = Debug.metric("NullCheckGuardRemoved");
-    private static final DebugMetric metricGuardsReplaced = Debug.metric("GuardsReplaced");
+    private static final DebugMetric metricObjectEqualsRemoved = Debug.metric("ObjectEqualsRemoved");
+    private static final DebugMetric metricGuardsRemoved = Debug.metric("GuardsRemoved");
+
+    private final MetaAccessProvider metaAccessProvider;
 
     private StructuredGraph graph;
 
+    public ConditionalEliminationPhase(MetaAccessProvider metaAccessProvider) {
+        this.metaAccessProvider = metaAccessProvider;
+    }
+
     @Override
     protected void run(StructuredGraph inputGraph) {
         graph = inputGraph;
@@ -57,14 +66,14 @@
     public static class State implements MergeableState<State> {
 
         private IdentityHashMap<ValueNode, ResolvedJavaType> knownTypes;
-        private HashSet<ValueNode> knownNotNull;
+        private HashSet<ValueNode> knownNonNull;
         private HashSet<ValueNode> knownNull;
         private IdentityHashMap<BooleanNode, ValueNode> trueConditions;
         private IdentityHashMap<BooleanNode, ValueNode> falseConditions;
 
         public State() {
             this.knownTypes = new IdentityHashMap<>();
-            this.knownNotNull = new HashSet<>();
+            this.knownNonNull = new HashSet<>();
             this.knownNull = new HashSet<>();
             this.trueConditions = new IdentityHashMap<>();
             this.falseConditions = new IdentityHashMap<>();
@@ -72,7 +81,7 @@
 
         public State(State other) {
             this.knownTypes = new IdentityHashMap<>(other.knownTypes);
-            this.knownNotNull = new HashSet<>(other.knownNotNull);
+            this.knownNonNull = new HashSet<>(other.knownNonNull);
             this.knownNull = new HashSet<>(other.knownNull);
             this.trueConditions = new IdentityHashMap<>(other.trueConditions);
             this.falseConditions = new IdentityHashMap<>(other.falseConditions);
@@ -81,11 +90,16 @@
         @Override
         public boolean merge(MergeNode merge, List<State> withStates) {
             IdentityHashMap<ValueNode, ResolvedJavaType> newKnownTypes = new IdentityHashMap<>();
-            HashSet<ValueNode> newKnownNotNull = new HashSet<>();
-            HashSet<ValueNode> newKnownNull = new HashSet<>();
             IdentityHashMap<BooleanNode, ValueNode> newTrueConditions = new IdentityHashMap<>();
             IdentityHashMap<BooleanNode, ValueNode> newFalseConditions = new IdentityHashMap<>();
 
+            HashSet<ValueNode> newKnownNull = new HashSet<>(knownNull);
+            HashSet<ValueNode> newKnownNonNull = new HashSet<>(knownNonNull);
+            for (State state : withStates) {
+                newKnownNull.retainAll(state.knownNull);
+                newKnownNonNull.retainAll(state.knownNonNull);
+            }
+
             for (Map.Entry<ValueNode, ResolvedJavaType> entry : knownTypes.entrySet()) {
                 ValueNode node = entry.getKey();
                 ResolvedJavaType type = entry.getValue();
@@ -101,30 +115,7 @@
                     newKnownTypes.put(node, type);
                 }
             }
-            for (ValueNode node : knownNotNull) {
-                boolean notNull = true;
-                for (State other : withStates) {
-                    if (!other.knownNotNull.contains(node)) {
-                        notNull = false;
-                        break;
-                    }
-                }
-                if (notNull) {
-                    newKnownNotNull.add(node);
-                }
-            }
-            for (ValueNode node : knownNull) {
-                boolean isNull = true;
-                for (State other : withStates) {
-                    if (!other.knownNull.contains(node)) {
-                        isNull = false;
-                        break;
-                    }
-                }
-                if (isNull) {
-                    newKnownNull.add(node);
-                }
-            }
+
             for (Map.Entry<BooleanNode, ValueNode> entry : trueConditions.entrySet()) {
                 BooleanNode check = entry.getKey();
                 ValueNode guard = entry.getValue();
@@ -162,14 +153,13 @@
                 }
             }
 
-            // this piece of code handles phis (merges the types and knownNull/knownNotNull of the
-            // values)
+            // this piece of code handles phis
             if (!(merge instanceof LoopBeginNode)) {
                 for (PhiNode phi : merge.phis()) {
                     if (phi.type() == PhiType.Value && phi.kind() == Kind.Object) {
                         ValueNode firstValue = phi.valueAt(0);
                         ResolvedJavaType type = getNodeType(firstValue);
-                        boolean notNull = knownNotNull.contains(firstValue);
+                        boolean nonNull = knownNonNull.contains(firstValue);
                         boolean isNull = knownNull.contains(firstValue);
 
                         for (int i = 0; i < withStates.size(); i++) {
@@ -177,14 +167,14 @@
                             ValueNode value = phi.valueAt(i + 1);
                             ResolvedJavaType otherType = otherState.getNodeType(value);
                             type = widen(type, otherType);
-                            notNull &= otherState.knownNotNull.contains(value);
+                            nonNull &= otherState.knownNonNull.contains(value);
                             isNull &= otherState.knownNull.contains(value);
                         }
                         if (type != null) {
                             newKnownTypes.put(phi, type);
                         }
-                        if (notNull) {
-                            newKnownNotNull.add(phi);
+                        if (nonNull) {
+                            newKnownNonNull.add(phi);
                         }
                         if (isNull) {
                             newKnownNull.add(phi);
@@ -194,7 +184,7 @@
             }
 
             this.knownTypes = newKnownTypes;
-            this.knownNotNull = newKnownNotNull;
+            this.knownNonNull = newKnownNonNull;
             this.knownNull = newKnownNull;
             this.trueConditions = newTrueConditions;
             this.falseConditions = newFalseConditions;
@@ -206,6 +196,14 @@
             return result == null ? node.objectStamp().type() : result;
         }
 
+        public boolean isNull(ValueNode value) {
+            return value.objectStamp().alwaysNull() || knownNull.contains(value);
+        }
+
+        public boolean isNonNull(ValueNode value) {
+            return value.objectStamp().nonNull() || knownNonNull.contains(value);
+        }
+
         @Override
         public void loopBegin(LoopBeginNode loopBegin) {
         }
@@ -222,6 +220,52 @@
         public State clone() {
             return new State(this);
         }
+
+        /**
+         * Adds information about a condition. If isTrue is true then the condition is known to
+         * hold, otherwise the condition is known not to hold.
+         */
+        public void addCondition(boolean isTrue, BooleanNode condition, ValueNode anchor) {
+            if (isTrue) {
+                if (!trueConditions.containsKey(condition)) {
+                    trueConditions.put(condition, anchor);
+                    metricConditionRegistered.increment();
+                }
+            } else {
+                if (!falseConditions.containsKey(condition)) {
+                    falseConditions.put(condition, anchor);
+                    metricConditionRegistered.increment();
+                }
+            }
+        }
+
+        /**
+         * Adds information about the nullness of a value. If isNull is true then the value is known
+         * to be null, otherwise the value is known to be non-null.
+         */
+        public void addNullness(boolean isNull, ValueNode value) {
+            if (isNull) {
+                if (!isNull(value)) {
+                    metricNullnessRegistered.increment();
+                    knownNull.add(value);
+                }
+            } else {
+                if (!isNonNull(value)) {
+                    metricNullnessRegistered.increment();
+                    knownNonNull.add(value);
+                }
+            }
+        }
+
+        public void addType(ResolvedJavaType type, ValueNode value) {
+            ResolvedJavaType knownType = getNodeType(value);
+            ResolvedJavaType newType = tighten(type, knownType);
+
+            if (newType != knownType) {
+                knownTypes.put(value, newType);
+                metricTypeRegistered.increment();
+            }
+        }
     }
 
     public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) {
@@ -241,8 +285,6 @@
             return a;
         } else if (a == b) {
             return a;
-        } else if (b.isAssignableFrom(a)) {
-            return a;
         } else if (a.isAssignableFrom(b)) {
             return b;
         } else {
@@ -252,131 +294,219 @@
 
     public class ConditionalElimination extends PostOrderNodeIterator<State> {
 
-        private BeginNode lastBegin = null;
+        private final BooleanNode trueConstant;
+        private final BooleanNode falseConstant;
 
         public ConditionalElimination(FixedNode start, State initialState) {
             super(start, initialState);
+            this.trueConstant = ConstantNode.forBoolean(true, graph);
+            this.falseConstant = ConstantNode.forBoolean(false, graph);
+        }
+
+        private void registerCondition(boolean isTrue, BooleanNode condition, ValueNode anchor) {
+            state.addCondition(isTrue, condition, anchor);
+
+            if (isTrue && condition instanceof InstanceOfNode) {
+                InstanceOfNode instanceOf = (InstanceOfNode) condition;
+                ValueNode object = instanceOf.object();
+                state.addNullness(false, object);
+                state.addType(instanceOf.type(), object);
+            } else if (condition instanceof IsNullNode) {
+                IsNullNode nullCheck = (IsNullNode) condition;
+                state.addNullness(isTrue, nullCheck.object());
+            } else if (condition instanceof ObjectEqualsNode) {
+                ObjectEqualsNode equals = (ObjectEqualsNode) condition;
+                ValueNode x = equals.x();
+                ValueNode y = equals.y();
+                if (isTrue) {
+                    if (state.isNull(x) && !state.isNull(y)) {
+                        metricObjectEqualsRegistered.increment();
+                        state.addNullness(true, y);
+                    } else if (!state.isNull(x) && state.isNull(y)) {
+                        metricObjectEqualsRegistered.increment();
+                        state.addNullness(true, x);
+                    }
+                    if (state.isNonNull(x) && !state.isNonNull(y)) {
+                        metricObjectEqualsRegistered.increment();
+                        state.addNullness(false, y);
+                    } else if (!state.isNonNull(x) && state.isNonNull(y)) {
+                        metricObjectEqualsRegistered.increment();
+                        state.addNullness(false, x);
+                    }
+                } else {
+                    if (state.isNull(x) && !state.isNonNull(y)) {
+                        metricObjectEqualsRegistered.increment();
+                        state.addNullness(true, y);
+                    } else if (!state.isNonNull(x) && state.isNull(y)) {
+                        metricObjectEqualsRegistered.increment();
+                        state.addNullness(true, x);
+                    }
+                }
+            }
+        }
+
+        private void registerControlSplitInfo(Node pred, BeginNode begin) {
+            assert pred != null && begin != null;
+
+            if (pred instanceof IfNode) {
+                IfNode ifNode = (IfNode) pred;
+
+                if (!(ifNode.condition() instanceof ConstantNode)) {
+                    registerCondition(begin == ifNode.trueSuccessor(), ifNode.condition(), begin);
+                }
+            } else if (pred instanceof TypeSwitchNode) {
+                TypeSwitchNode typeSwitch = (TypeSwitchNode) pred;
+
+                if (typeSwitch.value() instanceof LoadHubNode) {
+                    LoadHubNode loadHub = (LoadHubNode) typeSwitch.value();
+                    ResolvedJavaType type = null;
+                    for (int i = 0; i < typeSwitch.keyCount(); i++) {
+                        if (typeSwitch.keySuccessor(i) == begin) {
+                            if (type == null) {
+                                type = typeSwitch.typeAt(i);
+                            } else {
+                                type = widen(type, typeSwitch.typeAt(i));
+                            }
+                        }
+                    }
+                    if (type != null) {
+                        state.addNullness(false, loadHub.object());
+                        state.addType(type, loadHub.object());
+                    }
+                }
+            }
+        }
+
+        private void registerGuard(GuardNode guard) {
+            BooleanNode condition = guard.condition();
+
+            ValueNode existingGuards = guard.negated() ? state.falseConditions.get(condition) : state.trueConditions.get(condition);
+            if (existingGuards != null) {
+                guard.replaceAtUsages(existingGuards);
+                GraphUtil.killWithUnusedFloatingInputs(guard);
+                metricGuardsRemoved.increment();
+            } else {
+                BooleanNode replacement = evaluateCondition(condition, trueConstant, falseConstant);
+                if (replacement != null) {
+                    guard.setCondition(replacement);
+                    if (condition.usages().isEmpty()) {
+                        GraphUtil.killWithUnusedFloatingInputs(condition);
+                    }
+                    metricGuardsRemoved.increment();
+                } else {
+                    registerCondition(!guard.negated(), condition, guard);
+                }
+            }
+        }
+
+        /**
+         * Determines if, at the current point in the control flow, the condition is known to be
+         * true, false or unknown. In case of true or false the corresponding value is returned,
+         * otherwise null.
+         */
+        private <T extends ValueNode> T evaluateCondition(BooleanNode condition, T trueValue, T falseValue) {
+            if (state.trueConditions.containsKey(condition)) {
+                return trueValue;
+            } else if (state.falseConditions.containsKey(condition)) {
+                return falseValue;
+            } else {
+                if (condition instanceof InstanceOfNode) {
+                    InstanceOfNode instanceOf = (InstanceOfNode) condition;
+                    ValueNode object = instanceOf.object();
+                    if (state.isNull(object)) {
+                        metricInstanceOfRemoved.increment();
+                        return falseValue;
+                    } else if (state.isNonNull(object)) {
+                        ResolvedJavaType type = state.getNodeType(object);
+                        if (type != null && instanceOf.type().isAssignableFrom(type)) {
+                            metricInstanceOfRemoved.increment();
+                            return trueValue;
+                        }
+                    }
+                } else if (condition instanceof IsNullNode) {
+                    IsNullNode isNull = (IsNullNode) condition;
+                    ValueNode object = isNull.object();
+                    if (state.isNull(object)) {
+                        metricNullCheckRemoved.increment();
+                        return trueValue;
+                    } else if (state.isNonNull(object)) {
+                        metricNullCheckRemoved.increment();
+                        return falseValue;
+                    }
+                } else if (condition instanceof ObjectEqualsNode) {
+                    ObjectEqualsNode equals = (ObjectEqualsNode) condition;
+                    ValueNode x = equals.x();
+                    ValueNode y = equals.y();
+                    if (state.isNull(x) && state.isNonNull(y) || state.isNonNull(x) && state.isNull(y)) {
+                        metricObjectEqualsRemoved.increment();
+                        return falseValue;
+                    } else if (state.isNull(x) && state.isNull(y)) {
+                        metricObjectEqualsRemoved.increment();
+                        return trueValue;
+                    }
+                }
+            }
+            return null;
         }
 
         @Override
         protected void node(FixedNode node) {
             if (node instanceof BeginNode) {
                 BeginNode begin = (BeginNode) node;
-                lastBegin = begin;
                 Node pred = node.predecessor();
-                if (pred != null && pred instanceof IfNode) {
-                    IfNode ifNode = (IfNode) pred;
-                    if (!(ifNode.condition() instanceof ConstantNode)) {
-                        boolean isTrue = (node == ifNode.trueSuccessor());
-                        if (isTrue) {
-                            state.trueConditions.put(ifNode.condition(), begin);
-                        } else {
-                            state.falseConditions.put(ifNode.condition(), begin);
-                        }
-                    }
-                    if (ifNode.condition() instanceof InstanceOfNode) {
-                        InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition();
-                        if ((node == ifNode.trueSuccessor())) {
-                            ValueNode object = instanceOf.object();
-                            state.knownNotNull.add(object);
-                            state.knownTypes.put(object, tighten(instanceOf.type(), state.getNodeType(object)));
-                            metricInstanceOfRegistered.increment();
-                        }
-                    } else if (ifNode.condition() instanceof IsNullNode) {
-                        IsNullNode nullCheck = (IsNullNode) ifNode.condition();
-                        boolean isNull = (node == ifNode.trueSuccessor());
-                        if (isNull) {
-                            state.knownNull.add(nullCheck.object());
-                        } else {
-                            state.knownNotNull.add(nullCheck.object());
-                        }
-                        metricNullCheckRegistered.increment();
-                    }
+
+                if (pred != null) {
+                    registerControlSplitInfo(pred, begin);
                 }
                 for (GuardNode guard : begin.guards().snapshot()) {
-                    BooleanNode condition = guard.condition();
-                    ValueNode existingGuards = guard.negated() ? state.falseConditions.get(condition) : state.trueConditions.get(condition);
-                    if (existingGuards != null) {
-                        guard.replaceAtUsages(existingGuards);
-                        GraphUtil.killWithUnusedFloatingInputs(guard);
-                        metricGuardsReplaced.increment();
-                    } else {
-                        boolean removeCheck = false;
-                        if (condition instanceof IsNullNode) {
-                            IsNullNode isNull = (IsNullNode) condition;
-                            if (guard.negated() && state.knownNotNull.contains(isNull.object())) {
-                                removeCheck = true;
-                            } else if (!guard.negated() && state.knownNull.contains(isNull.object())) {
-                                removeCheck = true;
-                            }
-                            if (removeCheck) {
-                                metricNullCheckGuardRemoved.increment();
-                            }
-                        }
-                        if (removeCheck) {
-                            guard.replaceAtUsages(begin);
-                            GraphUtil.killWithUnusedFloatingInputs(guard);
-                        } else {
-                            if (guard.negated()) {
-                                state.falseConditions.put(condition, guard);
-                            } else {
-                                state.trueConditions.put(condition, guard);
-                            }
-                        }
-                    }
+                    registerGuard(guard);
                 }
             } else if (node instanceof CheckCastNode) {
                 CheckCastNode checkCast = (CheckCastNode) node;
-                ResolvedJavaType type = state.getNodeType(checkCast.object());
-                if (type != null && checkCast.type().isAssignableFrom(type)) {
+                ValueNode object = checkCast.object();
+                boolean isNull = state.isNull(object);
+                ResolvedJavaType type = state.getNodeType(object);
+                if (isNull || (type != null && checkCast.type().isAssignableFrom(type))) {
+                    boolean nonNull = state.isNonNull(object);
+                    ValueAnchorNode anchor = graph.add(new ValueAnchorNode());
                     PiNode piNode;
-                    boolean nonNull = state.knownNotNull.contains(checkCast.object());
-                    piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, nonNull ? StampFactory.declaredNonNull(type) : StampFactory.declared(type)));
+                    if (isNull) {
+                        ConstantNode nullObject = ConstantNode.forObject(null, metaAccessProvider, graph);
+                        piNode = graph.unique(new PiNode(nullObject, anchor, StampFactory.forConstant(nullObject.value, metaAccessProvider)));
+                    } else {
+                        piNode = graph.unique(new PiNode(object, anchor, StampFactory.declared(type, nonNull)));
+                    }
                     checkCast.replaceAtUsages(piNode);
-                    graph.removeFixed(checkCast);
+                    graph.replaceFixedWithFixed(checkCast, anchor);
                     metricCheckCastRemoved.increment();
                 }
             } else if (node instanceof IfNode) {
                 IfNode ifNode = (IfNode) node;
-                BooleanNode replaceWith = null;
                 BooleanNode compare = ifNode.condition();
+                BooleanNode replacement = evaluateCondition(compare, trueConstant, falseConstant);
 
-                if (state.trueConditions.containsKey(compare)) {
-                    replaceWith = ConstantNode.forBoolean(true, graph);
-                } else if (state.falseConditions.containsKey(compare)) {
-                    replaceWith = ConstantNode.forBoolean(false, graph);
-                } else {
-                    if (compare instanceof InstanceOfNode) {
-                        InstanceOfNode instanceOf = (InstanceOfNode) compare;
-                        ValueNode object = instanceOf.object();
-                        if (state.knownNull.contains(object)) {
-                            replaceWith = ConstantNode.forBoolean(false, graph);
-                        } else if (state.knownNotNull.contains(object)) {
-                            ResolvedJavaType type = state.getNodeType(object);
-                            if (type != null && instanceOf.type().isAssignableFrom(type)) {
-                                replaceWith = ConstantNode.forBoolean(true, graph);
+                if (replacement != null) {
+                    ifNode.setCondition(replacement);
+                    if (compare.usages().isEmpty()) {
+                        GraphUtil.killWithUnusedFloatingInputs(compare);
+                    }
+                }
+            } else if (node instanceof EndNode) {
+                EndNode endNode = (EndNode) node;
+                for (PhiNode phi : endNode.merge().phis()) {
+                    int index = endNode.merge().phiPredecessorIndex(endNode);
+                    ValueNode value = phi.valueAt(index);
+                    if (value instanceof ConditionalNode) {
+                        ConditionalNode materialize = (ConditionalNode) value;
+                        BooleanNode compare = materialize.condition();
+                        ValueNode replacement = evaluateCondition(compare, materialize.trueValue(), materialize.falseValue());
+
+                        if (replacement != null) {
+                            phi.setValueAt(index, replacement);
+                            if (materialize.usages().isEmpty()) {
+                                GraphUtil.killWithUnusedFloatingInputs(materialize);
                             }
                         }
-                        if (replaceWith != null) {
-                            metricInstanceOfRemoved.increment();
-                        }
-                    } else if (compare instanceof IsNullNode) {
-                        IsNullNode isNull = (IsNullNode) compare;
-                        ValueNode object = isNull.object();
-                        if (state.knownNull.contains(object)) {
-                            replaceWith = ConstantNode.forBoolean(true, graph);
-                        } else if (state.knownNotNull.contains(object)) {
-                            replaceWith = ConstantNode.forBoolean(false, graph);
-                        }
-                        if (replaceWith != null) {
-                            metricNullCheckRemoved.increment();
-                        }
-                    }
-                }
-                if (replaceWith != null) {
-                    ifNode.setCondition(replaceWith);
-                    if (compare.usages().isEmpty()) {
-                        GraphUtil.killWithUnusedFloatingInputs(compare);
                     }
                 }
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Mon Feb 11 10:41:29 2013 +0100
@@ -73,6 +73,7 @@
             return "Map=" + lastMemorySnapshot.toString() + " Loops=" + loops.toString();
         }
 
+        @SuppressWarnings("unchecked")
         @Override
         public boolean merge(MergeNode merge, List<MemoryMap> withStates) {
             if (withStates.size() == 0) {
@@ -106,7 +107,6 @@
                     keys.add(key);
                 }
             }
-            @SuppressWarnings("unchecked")
             IdentityHashMap<Object, ValueNode> newMemorySnapshot = (IdentityHashMap<Object, ValueNode>) lastMemorySnapshot.clone();
 
             for (Object key : keys) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GlobalValueNumberingPhase.java	Mon Feb 11 10:41:02 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common;
-
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
-
-public class GlobalValueNumberingPhase extends Phase {
-
-    public static final DebugMetric metricGlobalValueNumberingHits = Debug.metric("GlobalValueNumberingHits");
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        NodeBitMap visited = graph.createNodeBitMap();
-        for (Node n : graph.getNodes()) {
-            apply(n, visited, graph);
-        }
-    }
-
-    private void apply(Node n, NodeBitMap visited, StructuredGraph compilerGraph) {
-        if (!visited.isMarked(n)) {
-            visited.mark(n);
-            for (Node input : n.inputs()) {
-                apply(input, visited, compilerGraph);
-            }
-            if (n.getNodeClass().valueNumberable()) {
-                Node newNode = compilerGraph.findDuplicate(n);
-                if (newNode != null) {
-                    assert !(n instanceof FixedNode || newNode instanceof FixedNode);
-                    n.replaceAtUsages(newNode);
-                    n.safeDelete();
-                    metricGlobalValueNumberingHits.increment();
-                    Debug.log("GVN applied and new node is %1s", newNode);
-                }
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Mon Feb 11 10:41:29 2013 +0100
@@ -32,9 +32,11 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.PhasePlan.*;
+import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
-import com.oracle.graal.phases.common.InliningUtil.*;
+import com.oracle.graal.phases.common.InliningUtil.InlineInfo;
+import com.oracle.graal.phases.common.InliningUtil.InliningCallback;
+import com.oracle.graal.phases.common.InliningUtil.InliningPolicy;
 
 public class InliningPhase extends Phase implements InliningCallback {
 
@@ -52,6 +54,7 @@
     private final Assumptions assumptions;
     private final GraphCache cache;
     private final InliningPolicy inliningPolicy;
+    private final OptimisticOptimizations optimisticOpts;
     private CustomCanonicalizer customCanonicalizer;
 
     // Metrics
@@ -62,20 +65,22 @@
 
     public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Collection<Invoke> hints, Assumptions assumptions, GraphCache cache, PhasePlan plan,
                     OptimisticOptimizations optimisticOpts) {
-        this(target, runtime, assumptions, cache, plan, createInliningPolicy(assumptions, optimisticOpts, hints));
+        this(target, runtime, assumptions, cache, plan, createInliningPolicy(runtime, assumptions, optimisticOpts, hints), optimisticOpts);
     }
 
     public void setCustomCanonicalizer(CustomCanonicalizer customCanonicalizer) {
         this.customCanonicalizer = customCanonicalizer;
     }
 
-    public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, InliningPolicy inliningPolicy) {
+    public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, InliningPolicy inliningPolicy,
+                    OptimisticOptimizations optimisticOpts) {
         this.target = target;
         this.runtime = runtime;
         this.assumptions = assumptions;
         this.cache = cache;
         this.plan = plan;
         this.inliningPolicy = inliningPolicy;
+        this.optimisticOpts = optimisticOpts;
     }
 
     @Override
@@ -96,14 +101,12 @@
                         candidate.inline(graph, runtime, this, assumptions);
                         Debug.dump(graph, "after %s", candidate);
                         Iterable<Node> newNodes = graph.getNewNodes(mark);
+                        inliningPolicy.scanInvokes(newNodes);
                         if (GraalOptions.OptCanonicalizer) {
                             new CanonicalizerPhase(target, runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph);
                         }
                         metricInliningPerformed.increment();
-
-                        inliningPolicy.scanInvokes(newNodes);
                     } catch (BailoutException bailout) {
-                        // TODO determine if we should really bail out of the whole compilation.
                         throw bailout;
                     } catch (AssertionError e) {
                         throw new GraalInternalError(e).addContext(candidate.toString());
@@ -112,6 +115,8 @@
                     } catch (GraalInternalError e) {
                         throw e.addContext(candidate.toString());
                     }
+                } else if (optimisticOpts.devirtualizeInvokes()) {
+                    candidate.tryToDevirtualizeInvoke(graph, runtime, assumptions);
                 }
             }
         }
@@ -153,171 +158,174 @@
         boolean isWorthInlining(InlineInfo info);
     }
 
-    private abstract static class AbstractInliningDecision implements InliningDecision {
-
-        protected static boolean decideSizeBasedInlining(InlineInfo info, double maxSize) {
-            assert !Double.isNaN(info.weight()) && !Double.isNaN(maxSize);
-            boolean success = info.weight() <= maxSize;
-            if (GraalOptions.Debug) {
-                String formatterString = success ? "(size %f <= %f)" : "(too large %f > %f)";
-                InliningUtil.logInliningDecision(info, success, formatterString, info.weight(), maxSize);
-            }
-            return success;
-        }
+    private static class GreedySizeBasedInliningDecision implements InliningDecision {
 
-        protected static boolean checkCompiledCodeSize(InlineInfo info) {
-            if (GraalOptions.SmallCompiledCodeSize >= 0 && info.compiledCodeSize() > GraalOptions.SmallCompiledCodeSize) {
-                InliningUtil.logNotInlinedMethod(info, "(CompiledCodeSize %d > %d)", info.compiledCodeSize(), GraalOptions.SmallCompiledCodeSize);
-                return false;
-            }
-            return true;
-        }
-
-        protected static double getRelevance(Invoke invoke) {
-            if (GraalOptions.UseRelevanceBasedInlining) {
-                return invoke.inliningRelevance();
-            } else {
-                return invoke.probability();
-            }
-        }
-    }
-
-    private static class C1StaticSizeBasedInliningDecision extends AbstractInliningDecision {
-
-        @Override
-        public boolean isWorthInlining(InlineInfo info) {
-            double maxSize = Math.max(GraalOptions.MaximumTrivialSize, Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize);
-            return decideSizeBasedInlining(info, maxSize);
-        }
-    }
+        private final GraalCodeCacheProvider runtime;
+        private final Collection<Invoke> hints;
 
-    private static class MinimumCodeSizeBasedInliningDecision extends AbstractInliningDecision {
-
-        @Override
-        public boolean isWorthInlining(InlineInfo info) {
-            assert GraalOptions.ProbabilityAnalysis;
-            if (!checkCompiledCodeSize(info)) {
-                return false;
-            }
-
-            double inlineWeight = Math.min(GraalOptions.RatioCapForInlining, getRelevance(info.invoke()));
-            double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize * inlineWeight;
-            maxSize = Math.max(GraalOptions.MaximumTrivialSize, maxSize);
-
-            return decideSizeBasedInlining(info, maxSize);
+        public GreedySizeBasedInliningDecision(GraalCodeCacheProvider runtime, Collection<Invoke> hints) {
+            this.runtime = runtime;
+            this.hints = hints;
         }
-    }
-
-    private static class DynamicSizeBasedInliningDecision extends AbstractInliningDecision {
-
-        @Override
-        public boolean isWorthInlining(InlineInfo info) {
-            assert GraalOptions.ProbabilityAnalysis;
-            if (!checkCompiledCodeSize(info)) {
-                return false;
-            }
-
-            double relevance = getRelevance(info.invoke());
-            double inlineBoost = Math.min(GraalOptions.RatioCapForInlining, relevance) + Math.log10(Math.max(1, relevance - GraalOptions.RatioCapForInlining + 1));
-            double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize;
-            maxSize = maxSize + maxSize * inlineBoost;
-            maxSize = Math.min(GraalOptions.MaximumGreedyInlineSize, Math.max(GraalOptions.MaximumTrivialSize, maxSize));
-
-            return decideSizeBasedInlining(info, maxSize);
-        }
-    }
-
-    private static class GreedySizeBasedInliningDecision extends AbstractInliningDecision {
 
         @Override
         public boolean isWorthInlining(InlineInfo info) {
             assert GraalOptions.ProbabilityAnalysis;
-            if (!checkCompiledCodeSize(info)) {
-                return false;
+            /*
+             * TODO (chaeubl): invoked methods that are on important paths but not yet compiled ->
+             * will be compiled anyways and it is likely that we are the only caller... might be
+             * useful to inline those methods but increases bootstrap time (maybe those methods are
+             * also getting queued in the compilation queue concurrently)
+             */
+
+            if (GraalOptions.AlwaysInlineIntrinsics && onlyIntrinsics(info)) {
+                return InliningUtil.logInlinedMethod(info, "intrinsic");
             }
 
-            double maxSize = GraalOptions.MaximumGreedyInlineSize;
-            if (GraalOptions.InliningBonusPerTransferredValue != 0) {
-                Signature signature = info.invoke().methodCallTarget().targetMethod().getSignature();
-                int transferredValues = signature.getParameterCount(!Modifier.isStatic(info.invoke().methodCallTarget().targetMethod().getModifiers()));
-                if (signature.getReturnKind() != Kind.Void) {
-                    transferredValues++;
+            int bytecodeSize = bytecodeCodeSize(info);
+            int complexity = compilationComplexity(info);
+            int compiledCodeSize = compiledCodeSize(info);
+            double relevance = info.invoke().inliningRelevance();
+
+            /*
+             * as long as the compiled code size is small enough (or the method was not yet
+             * compiled), we can do a pretty general inlining that suits most situations
+             */
+            if (compiledCodeSize < GraalOptions.SmallCompiledCodeSize) {
+                if (isTrivialInlining(bytecodeSize, complexity, compiledCodeSize)) {
+                    return InliningUtil.logInlinedMethod(info, "trivial (bytecodes=%d, complexity=%d, codeSize=%d)", bytecodeSize, complexity, compiledCodeSize);
                 }
-                maxSize += transferredValues * GraalOptions.InliningBonusPerTransferredValue;
+
+                if (canInlineRelevanceBased(relevance, bytecodeSize, complexity, compiledCodeSize)) {
+                    return InliningUtil.logInlinedMethod(info, "relevance-based (relevance=%f, bytecodes=%d, complexity=%d, codeSize=%d)", relevance, bytecodeSize, complexity, compiledCodeSize);
+                }
             }
 
-            double inlineRatio = Math.min(GraalOptions.RatioCapForInlining, getRelevance(info.invoke()));
-            maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * maxSize * inlineRatio;
-            maxSize = Math.max(maxSize, GraalOptions.MaximumTrivialSize);
+            /*
+             * the normal inlining did not fit this invoke, so check if we have any reason why we
+             * should still do the inlining
+             */
+            double probability = info.invoke().probability();
+            int transferredValues = numberOfTransferredValues(info);
+            int invokeUsages = countInvokeUsages(info);
+            int moreSpecificArguments = countMoreSpecificArgumentInfo(info);
+            int level = info.level();
+            boolean preferredInvoke = hints != null && hints.contains(info.invoke());
 
-            return decideSizeBasedInlining(info, maxSize);
+            // TODO (chaeubl): compute metric that is used to check if this method should be inlined
+
+            return InliningUtil.logNotInlinedMethod(info,
+                            "(relevance=%f, bytecodes=%d, complexity=%d, codeSize=%d, probability=%f, transferredValues=%d, invokeUsages=%d, moreSpecificArguments=%d, level=%d, preferred=%b)",
+                            relevance, bytecodeSize, complexity, compiledCodeSize, probability, transferredValues, invokeUsages, moreSpecificArguments, level, preferredInvoke);
         }
-    }
+
+        private static boolean isTrivialInlining(int bytecodeSize, int complexity, int compiledCodeSize) {
+            return bytecodeSize < GraalOptions.TrivialBytecodeSize || complexity < GraalOptions.TrivialComplexity || compiledCodeSize > 0 && compiledCodeSize < GraalOptions.TrivialCompiledCodeSize;
+        }
 
-    private static class GreedyMachineCodeInliningDecision extends AbstractInliningDecision {
+        private static boolean canInlineRelevanceBased(double relevance, int bytecodeSize, int complexity, int compiledCodeSize) {
+            return bytecodeSize < computeMaximumSize(relevance, GraalOptions.NormalBytecodeSize) || complexity < computeMaximumSize(relevance, GraalOptions.NormalComplexity) || compiledCodeSize > 0 &&
+                            compiledCodeSize < computeMaximumSize(relevance, GraalOptions.NormalCompiledCodeSize);
+        }
 
-        @Override
-        public boolean isWorthInlining(InlineInfo info) {
-            assert GraalOptions.ProbabilityAnalysis;
+        private static double computeMaximumSize(double relevance, int configuredMaximum) {
+            double inlineRatio = Math.min(GraalOptions.RelevanceCapForInlining, relevance);
+            return configuredMaximum * inlineRatio;
+        }
+
+        private static int numberOfTransferredValues(InlineInfo info) {
+            Signature signature = info.invoke().methodCallTarget().targetMethod().getSignature();
+            int transferredValues = signature.getParameterCount(!Modifier.isStatic(info.invoke().methodCallTarget().targetMethod().getModifiers()));
+            if (signature.getReturnKind() != Kind.Void) {
+                transferredValues++;
+            }
+            return transferredValues;
+        }
 
-            double maxSize = GraalOptions.MaximumGreedyInlineSize;
-            double inlineRatio = Math.min(GraalOptions.RatioCapForInlining, getRelevance(info.invoke()));
-            maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * maxSize * inlineRatio;
-            maxSize = Math.max(maxSize, GraalOptions.MaximumTrivialSize);
-
-            return decideSizeBasedInlining(info, maxSize);
+        private static int countInvokeUsages(InlineInfo info) {
+            // inlining calls with lots of usages simplifies the caller
+            int usages = 0;
+            for (Node n : info.invoke().node().usages()) {
+                if (!(n instanceof FrameState)) {
+                    usages++;
+                }
+            }
+            return usages;
         }
-    }
 
-    private static class BytecodeSizeBasedWeightComputationPolicy implements WeightComputationPolicy {
+        private int countMoreSpecificArgumentInfo(InlineInfo info) {
+            /*
+             * inlining invokes where the caller has very specific information about the passed
+             * argument simplifies the callee
+             */
+            int moreSpecificArgumentInfo = 0;
+            boolean isStatic = info.invoke().methodCallTarget().isStatic();
+            int signatureOffset = isStatic ? 0 : 1;
+            NodeInputList arguments = info.invoke().methodCallTarget().arguments();
+            ResolvedJavaMethod targetMethod = info.invoke().methodCallTarget().targetMethod();
+            ResolvedJavaType methodHolderClass = targetMethod.getDeclaringClass();
+            Signature signature = targetMethod.getSignature();
 
-        @Override
-        public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) {
-            if (GraalOptions.AlwaysInlineIntrinsics && InliningUtil.canIntrinsify(method)) {
-                return 0;
+            for (int i = 0; i < arguments.size(); i++) {
+                Node n = arguments.get(i);
+                if (n instanceof ConstantNode) {
+                    moreSpecificArgumentInfo++;
+                } else if (n instanceof ValueNode && !((ValueNode) n).kind().isPrimitive()) {
+                    ResolvedJavaType actualType = ((ValueNode) n).stamp().javaType(runtime);
+                    JavaType declaredType;
+                    if (i == 0 && !isStatic) {
+                        declaredType = methodHolderClass;
+                    } else {
+                        declaredType = signature.getParameterType(i - signatureOffset, methodHolderClass);
+                    }
+
+                    if (declaredType instanceof ResolvedJavaType && !actualType.equals(declaredType) && ((ResolvedJavaType) declaredType).isAssignableFrom(actualType)) {
+                        moreSpecificArgumentInfo++;
+                    }
+                }
+
             }
 
-            double codeSize = method.getCodeSize();
-            if (preferredInvoke) {
-                codeSize = codeSize / GraalOptions.BoostInliningForEscapeAnalysis;
-            }
-            return codeSize;
+            return moreSpecificArgumentInfo;
         }
-    }
 
-    private static class ComplexityBasedWeightComputationPolicy implements WeightComputationPolicy {
-
-        @Override
-        public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) {
-            if (GraalOptions.AlwaysInlineIntrinsics && InliningUtil.canIntrinsify(method)) {
-                return 0;
+        private static int bytecodeCodeSize(InlineInfo info) {
+            int result = 0;
+            for (int i = 0; i < info.numberOfMethods(); i++) {
+                result += info.methodAt(i).getCodeSize();
             }
+            return result;
+        }
 
-            double complexity = method.getCompilationComplexity();
-            if (preferredInvoke) {
-                complexity = complexity / GraalOptions.BoostInliningForEscapeAnalysis;
+        private static int compilationComplexity(InlineInfo info) {
+            int result = 0;
+            for (int i = 0; i < info.numberOfMethods(); i++) {
+                result += info.methodAt(i).getCompilationComplexity();
             }
-            return complexity;
+            return result;
         }
-    }
 
-    private static class CompiledCodeSizeWeightComputationPolicy implements WeightComputationPolicy {
+        private static int compiledCodeSize(InlineInfo info) {
+            int result = 0;
+            for (int i = 0; i < info.numberOfMethods(); i++) {
+                result += info.methodAt(i).getCompiledCodeSize();
+            }
+            return result;
+        }
 
-        @Override
-        public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) {
-            if (GraalOptions.AlwaysInlineIntrinsics && InliningUtil.canIntrinsify(method)) {
-                return 0;
+        private static boolean onlyIntrinsics(InlineInfo info) {
+            for (int i = 0; i < info.numberOfMethods(); i++) {
+                if (!InliningUtil.canIntrinsify(info.methodAt(i))) {
+                    return false;
+                }
             }
-
-            int compiledCodeSize = method.getCompiledCodeSize();
-            return compiledCodeSize > 0 ? compiledCodeSize : method.getCodeSize() * 10;
+            return true;
         }
     }
 
     private static class CFInliningPolicy implements InliningPolicy {
 
         private final InliningDecision inliningDecision;
-        private final WeightComputationPolicy weightComputationPolicy;
         private final Collection<Invoke> hints;
         private final Assumptions assumptions;
         private final OptimisticOptimizations optimisticOpts;
@@ -325,10 +333,8 @@
         private NodeBitMap visitedFixedNodes;
         private FixedNode invokePredecessor;
 
-        public CFInliningPolicy(InliningDecision inliningPolicy, WeightComputationPolicy weightComputationPolicy, Collection<Invoke> hints, Assumptions assumptions,
-                        OptimisticOptimizations optimisticOpts) {
+        public CFInliningPolicy(InliningDecision inliningPolicy, Collection<Invoke> hints, Assumptions assumptions, OptimisticOptimizations optimisticOpts) {
             this.inliningDecision = inliningPolicy;
-            this.weightComputationPolicy = weightComputationPolicy;
             this.hints = hints;
             this.assumptions = assumptions;
             this.optimisticOpts = optimisticOpts;
@@ -347,7 +353,7 @@
 
         public InlineInfo next() {
             Invoke invoke = sortedInvokes.pop();
-            InlineInfo info = InliningUtil.getInlineInfo(invoke, assumptions, this, optimisticOpts);
+            InlineInfo info = InliningUtil.getInlineInfo(invoke, assumptions, optimisticOpts);
             if (info != null) {
                 invokePredecessor = (FixedNode) info.invoke().predecessor();
                 assert invokePredecessor.isAlive();
@@ -368,171 +374,105 @@
         }
 
         public void scanInvokes(Iterable<? extends Node> newNodes) {
-            scanGraphForInvokes(invokePredecessor);
+            assert invokePredecessor.isAlive();
+            int invokes = scanGraphForInvokes(invokePredecessor);
+            assert invokes == countInvokes(newNodes);
         }
 
-        private void scanGraphForInvokes(FixedNode start) {
+        private int scanGraphForInvokes(FixedNode start) {
             ArrayList<Invoke> invokes = new InliningIterator(start, visitedFixedNodes).apply();
 
             // insert the newly found invokes in their correct control-flow order
             for (int i = invokes.size() - 1; i >= 0; i--) {
-                sortedInvokes.addFirst(invokes.get(i));
-            }
-        }
-
-        public double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke) {
-            boolean preferredInvoke = hints != null && hints.contains(invoke);
-            return weightComputationPolicy.computeWeight(caller, method, invoke, preferredInvoke);
-        }
-    }
-
-    private static class PriorityInliningPolicy implements InliningPolicy {
+                Invoke invoke = invokes.get(i);
+                assert !sortedInvokes.contains(invoke);
+                sortedInvokes.addFirst(invoke);
 
-        private final InliningDecision inliningDecision;
-        private final WeightComputationPolicy weightComputationPolicy;
-        private final Collection<Invoke> hints;
-        private final Assumptions assumptions;
-        private final OptimisticOptimizations optimisticOpts;
-        private final PriorityQueue<InlineInfo> sortedCandidates;
-
-        public PriorityInliningPolicy(InliningDecision inliningPolicy, WeightComputationPolicy weightComputationPolicy, Collection<Invoke> hints, Assumptions assumptions,
-                        OptimisticOptimizations optimisticOpts) {
-            this.inliningDecision = inliningPolicy;
-            this.weightComputationPolicy = weightComputationPolicy;
-            this.hints = hints;
-            this.assumptions = assumptions;
-            this.optimisticOpts = optimisticOpts;
-            sortedCandidates = new PriorityQueue<>();
-        }
-
-        public boolean continueInlining(StructuredGraph graph) {
-            if (graph.getNodeCount() >= GraalOptions.MaximumDesiredSize) {
-                InliningUtil.logInliningDecision("inlining is cut off by MaximumDesiredSize");
-                metricInliningStoppedByMaxDesiredSize.increment();
-                return false;
             }
 
-            return !sortedCandidates.isEmpty();
+            return invokes.size();
         }
 
-        public InlineInfo next() {
-            // refresh cached info before using it (it might have been in the queue for a long time)
-            InlineInfo info = sortedCandidates.remove();
-            return InliningUtil.getInlineInfo(info.invoke(), assumptions, this, optimisticOpts);
-        }
-
-        @Override
-        public boolean isWorthInlining(InlineInfo info) {
-            return inliningDecision.isWorthInlining(info);
-        }
-
-        @SuppressWarnings("unchecked")
-        public void initialize(StructuredGraph graph) {
-            if (hints == null) {
-                scanInvokes(graph.getNodes(InvokeNode.class));
-                scanInvokes(graph.getNodes(InvokeWithExceptionNode.class));
-            } else {
-                scanInvokes((Iterable<? extends Node>) (Iterable<?>) hints);
-            }
-        }
-
-        public void scanInvokes(Iterable<? extends Node> nodes) {
-            for (Node node : nodes) {
-                if (node != null) {
-                    if (node instanceof Invoke) {
-                        Invoke invoke = (Invoke) node;
-                        scanInvoke(invoke);
-                    }
-                    for (Node usage : node.usages().filterInterface(Invoke.class).snapshot()) {
-                        scanInvoke((Invoke) usage);
-                    }
+        private static int countInvokes(Iterable<? extends Node> nodes) {
+            int count = 0;
+            for (Node n : nodes) {
+                if (n instanceof Invoke) {
+                    count++;
                 }
             }
-        }
-
-        private void scanInvoke(Invoke invoke) {
-            InlineInfo info = InliningUtil.getInlineInfo(invoke, assumptions, this, optimisticOpts);
-            if (info != null) {
-                sortedCandidates.add(info);
-            }
-        }
-
-        @Override
-        public double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke) {
-            boolean preferredInvoke = hints != null && hints.contains(invoke);
-            return weightComputationPolicy.computeWeight(caller, method, invoke, preferredInvoke);
+            return count;
         }
     }
 
     private static class InliningIterator {
 
         private final FixedNode start;
-        private final NodeBitMap processedNodes;
-
         private final Deque<FixedNode> nodeQueue;
         private final NodeBitMap queuedNodes;
 
         public InliningIterator(FixedNode start, NodeBitMap visitedFixedNodes) {
             this.start = start;
-            this.processedNodes = visitedFixedNodes;
-
             this.nodeQueue = new ArrayDeque<>();
-            this.queuedNodes = visitedFixedNodes.copy();
-
+            this.queuedNodes = visitedFixedNodes;
             assert start.isAlive();
         }
 
         public ArrayList<Invoke> apply() {
             ArrayList<Invoke> invokes = new ArrayList<>();
-            FixedNode current = start;
-            do {
+            FixedNode current;
+            forcedQueue(start);
+
+            while ((current = nextQueuedNode()) != null) {
                 assert current.isAlive();
-                processedNodes.mark(current);
 
-                if (current instanceof InvokeWithExceptionNode || current instanceof InvokeNode) {
-                    invokes.add((Invoke) current);
+                if (current instanceof Invoke) {
+                    if (current != start) {
+                        invokes.add((Invoke) current);
+                    }
                     queueSuccessors(current);
-                    current = nextQueuedNode();
                 } else if (current instanceof LoopBeginNode) {
-                    current = ((LoopBeginNode) current).next();
-                    assert current != null;
+                    queueSuccessors(current);
                 } else if (current instanceof LoopEndNode) {
-                    current = nextQueuedNode();
+                    // nothing todo
                 } else if (current instanceof MergeNode) {
-                    current = ((MergeNode) current).next();
-                    assert current != null;
+                    queueSuccessors(current);
                 } else if (current instanceof FixedWithNextNode) {
                     queueSuccessors(current);
-                    current = nextQueuedNode();
                 } else if (current instanceof EndNode) {
                     queueMerge((EndNode) current);
-                    current = nextQueuedNode();
                 } else if (current instanceof DeoptimizeNode) {
-                    current = nextQueuedNode();
+                    // nothing todo
                 } else if (current instanceof ReturnNode) {
-                    current = nextQueuedNode();
+                    // nothing todo
                 } else if (current instanceof UnwindNode) {
-                    current = nextQueuedNode();
+                    // nothing todo
                 } else if (current instanceof ControlSplitNode) {
                     queueSuccessors(current);
-                    current = nextQueuedNode();
                 } else {
                     assert false : current;
                 }
-            } while (current != null);
+            }
 
             return invokes;
         }
 
         private void queueSuccessors(FixedNode x) {
             for (Node node : x.successors()) {
-                if (node != null && !queuedNodes.isMarked(node)) {
-                    queuedNodes.mark(node);
-                    nodeQueue.addFirst((FixedNode) node);
-                }
+                queue(node);
             }
         }
 
+        private void queue(Node node) {
+            if (node != null && !queuedNodes.isMarked(node)) {
+                forcedQueue(node);
+            }
+        }
+
+        private void forcedQueue(Node node) {
+            queuedNodes.mark(node);
+            nodeQueue.addFirst((FixedNode) node);
+        }
+
         private FixedNode nextQueuedNode() {
             if (nodeQueue.isEmpty()) {
                 return null;
@@ -553,7 +493,7 @@
 
         private boolean visitedAllEnds(MergeNode merge) {
             for (int i = 0; i < merge.forwardEndCount(); i++) {
-                if (!processedNodes.isMarked(merge.forwardEndAt(i))) {
+                if (!queuedNodes.isMarked(merge.forwardEndAt(i))) {
                     return false;
                 }
             }
@@ -561,49 +501,8 @@
         }
     }
 
-    private static InliningPolicy createInliningPolicy(Assumptions assumptions, OptimisticOptimizations optimisticOpts, Collection<Invoke> hints) {
-        switch (GraalOptions.InliningPolicy) {
-            case 0:
-                return new CFInliningPolicy(createInliningDecision(), createWeightComputationPolicy(), hints, assumptions, optimisticOpts);
-            case 1:
-                return new PriorityInliningPolicy(createInliningDecision(), createWeightComputationPolicy(), hints, assumptions, optimisticOpts);
-            default:
-                GraalInternalError.shouldNotReachHere();
-                return null;
-        }
-    }
-
-    private static InliningDecision createInliningDecision() {
-        switch (GraalOptions.InliningDecision) {
-            case 1:
-                return new C1StaticSizeBasedInliningDecision();
-            case 2:
-                return new MinimumCodeSizeBasedInliningDecision();
-            case 3:
-                return new DynamicSizeBasedInliningDecision();
-            case 4:
-                return new GreedySizeBasedInliningDecision();
-            case 5:
-                return new GreedyMachineCodeInliningDecision();
-            default:
-                GraalInternalError.shouldNotReachHere();
-                return null;
-        }
-    }
-
-    private static WeightComputationPolicy createWeightComputationPolicy() {
-        switch (GraalOptions.WeightComputationPolicy) {
-            case 0:
-                throw new GraalInternalError("removed because of invokation counter changes");
-            case 1:
-                return new BytecodeSizeBasedWeightComputationPolicy();
-            case 2:
-                return new ComplexityBasedWeightComputationPolicy();
-            case 3:
-                return new CompiledCodeSizeWeightComputationPolicy();
-            default:
-                GraalInternalError.shouldNotReachHere();
-                return null;
-        }
+    private static InliningPolicy createInliningPolicy(GraalCodeCacheProvider runtime, Assumptions assumptions, OptimisticOptimizations optimisticOpts, Collection<Invoke> hints) {
+        InliningDecision inliningDecision = new GreedySizeBasedInliningDecision(runtime, hints);
+        return new CFInliningPolicy(inliningDecision, hints, assumptions, optimisticOpts);
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Mon Feb 11 10:41:29 2013 +0100
@@ -70,18 +70,13 @@
 
         void scanInvokes(Iterable<? extends Node> newNodes);
 
-        double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke);
-
         boolean isWorthInlining(InlineInfo info);
     }
 
-    public interface WeightComputationPolicy {
+    public static boolean logNotInlinedMethod(InlineInfo info, String msg, Object... args) {
 
-        double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke);
-    }
-
-    public static void logNotInlinedMethod(InlineInfo info, String msg, Object... args) {
         logInliningDecision(info, false, msg, args);
+        return false;
     }
 
     public static void logInliningDecision(InlineInfo info, boolean success, String msg, final Object... args) {
@@ -99,6 +94,11 @@
         });
     }
 
+    public static boolean logInlinedMethod(InlineInfo info, String string, Object... args) {
+        logInliningDecision(info, true, string, args);
+        return true;
+    }
+
     private static boolean logNotInlinedMethodAndReturnFalse(Invoke invoke, String msg) {
         if (shouldLogInliningDecision()) {
             String methodString = invoke.toString() + (invoke.callTarget() == null ? " callTarget=null" : invoke.callTarget().targetName());
@@ -135,7 +135,7 @@
         logInliningDecision(inliningMsg, args);
     }
 
-    private static boolean shouldLogInliningDecision() {
+    public static boolean shouldLogInliningDecision() {
         return Debug.scope(inliningDecisionsScopeString, new Callable<Boolean>() {
 
             public Boolean call() {
@@ -178,49 +178,43 @@
      * The weight is the amortized weight of the additional code - so smaller is better. The level
      * is the number of nested inlinings that lead to this invoke.
      */
-    public interface InlineInfo extends Comparable<InlineInfo> {
+    public interface InlineInfo {
 
         Invoke invoke();
 
-        double weight();
-
         int level();
 
-        int compiledCodeSize();
+        int numberOfMethods();
 
-        int compareTo(InlineInfo o);
+        ResolvedJavaMethod methodAt(int index);
 
         /**
          * Performs the inlining described by this object and returns the node that represents the
          * return value of the inlined method (or null for void methods and methods that have no
          * non-exceptional exit).
+         **/
+        void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions);
+
+        /**
+         * Try to make the call static bindable to avoid interface and virtual method calls.
          */
-        void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions);
+        void tryToDevirtualizeInvoke(StructuredGraph graph, GraalCodeCacheProvider runtime, Assumptions assumptions);
     }
 
     public abstract static class AbstractInlineInfo implements InlineInfo {
 
         protected final Invoke invoke;
-        protected final double weight;
 
-        public AbstractInlineInfo(Invoke invoke, double weight) {
+        public AbstractInlineInfo(Invoke invoke) {
             this.invoke = invoke;
-            this.weight = weight;
         }
 
         @Override
-        public int compareTo(InlineInfo o) {
-            return (weight < o.weight()) ? -1 : (weight > o.weight()) ? 1 : 0;
-        }
-
         public Invoke invoke() {
             return invoke;
         }
 
-        public double weight() {
-            return weight;
-        }
-
+        @Override
         public int level() {
             return computeInliningLevel(invoke);
         }
@@ -260,7 +254,7 @@
             }
         }
 
-        private static StructuredGraph getGraph(final ResolvedJavaMethod concrete, final InliningCallback callback) {
+        protected static StructuredGraph getGraph(final ResolvedJavaMethod concrete, final InliningCallback callback) {
             return Debug.scope("GetInliningGraph", concrete, new Callable<StructuredGraph>() {
 
                 @Override
@@ -270,6 +264,12 @@
                 }
             });
         }
+
+        protected void replaceInvokeCallTarget(StructuredGraph graph, InvokeKind invokeKind, ResolvedJavaMethod targetMethod) {
+            MethodCallTargetNode oldCallTarget = invoke.methodCallTarget();
+            MethodCallTargetNode newCallTarget = graph.add(new MethodCallTargetNode(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType()));
+            invoke.node().replaceFirstInput(oldCallTarget, newCallTarget);
+        }
     }
 
     /**
@@ -280,8 +280,8 @@
 
         public final ResolvedJavaMethod concrete;
 
-        public ExactInlineInfo(Invoke invoke, double weight, ResolvedJavaMethod concrete) {
-            super(invoke, weight);
+        public ExactInlineInfo(Invoke invoke, ResolvedJavaMethod concrete) {
+            super(invoke);
             this.concrete = concrete;
         }
 
@@ -291,8 +291,19 @@
         }
 
         @Override
-        public int compiledCodeSize() {
-            return InliningUtil.compiledCodeSize(concrete);
+        public void tryToDevirtualizeInvoke(StructuredGraph graph, GraalCodeCacheProvider runtime, Assumptions assumptions) {
+            // nothing todo, can already be bound statically
+        }
+
+        @Override
+        public int numberOfMethods() {
+            return 1;
+        }
+
+        @Override
+        public ResolvedJavaMethod methodAt(int index) {
+            assert index == 0;
+            return concrete;
         }
 
         @Override
@@ -311,20 +322,36 @@
         public final ResolvedJavaMethod concrete;
         public final ResolvedJavaType type;
 
-        public TypeGuardInlineInfo(Invoke invoke, double weight, ResolvedJavaMethod concrete, ResolvedJavaType type) {
-            super(invoke, weight);
+        public TypeGuardInlineInfo(Invoke invoke, ResolvedJavaMethod concrete, ResolvedJavaType type) {
+            super(invoke);
             this.concrete = concrete;
             this.type = type;
         }
 
         @Override
-        public int compiledCodeSize() {
-            return InliningUtil.compiledCodeSize(concrete);
+        public int numberOfMethods() {
+            return 1;
+        }
+
+        @Override
+        public ResolvedJavaMethod methodAt(int index) {
+            assert index == 0;
+            return concrete;
         }
 
         @Override
         public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions) {
-            // receiver null check must be before the type check
+            createGuard(graph, runtime);
+            inline(invoke, concrete, callback, assumptions, false);
+        }
+
+        @Override
+        public void tryToDevirtualizeInvoke(StructuredGraph graph, GraalCodeCacheProvider runtime, Assumptions assumptions) {
+            createGuard(graph, runtime);
+            replaceInvokeCallTarget(graph, InvokeKind.Special, concrete);
+        }
+
+        private void createGuard(StructuredGraph graph, GraalCodeCacheProvider runtime) {
             InliningUtil.receiverNullCheck(invoke);
             ValueNode receiver = invoke.methodCallTarget().receiver();
             ConstantNode typeHub = ConstantNode.forConstant(type.getEncoding(Representation.ObjectHub), runtime, graph);
@@ -340,8 +367,6 @@
             graph.addBeforeFixed(invoke.node(), receiverHub);
             graph.addBeforeFixed(invoke.node(), guard);
             graph.addBeforeFixed(invoke.node(), anchor);
-
-            inline(invoke, concrete, callback, assumptions, false);
         }
 
         @Override
@@ -362,8 +387,8 @@
         public final int[] typesToConcretes;
         public final double notRecordedTypeProbability;
 
-        public MultiTypeGuardInlineInfo(Invoke invoke, double weight, ArrayList<ResolvedJavaMethod> concretes, ArrayList<ProfiledType> ptypes, int[] typesToConcretes, double notRecordedTypeProbability) {
-            super(invoke, weight);
+        public MultiTypeGuardInlineInfo(Invoke invoke, ArrayList<ResolvedJavaMethod> concretes, ArrayList<ProfiledType> ptypes, int[] typesToConcretes, double notRecordedTypeProbability) {
+            super(invoke);
             assert concretes.size() > 0 && concretes.size() <= ptypes.size() : "must have at least one method but no more than types methods";
             assert ptypes.size() == typesToConcretes.length : "array lengths must match";
 
@@ -374,33 +399,37 @@
         }
 
         @Override
-        public int compiledCodeSize() {
-            int result = 0;
-            for (ResolvedJavaMethod m : concretes) {
-                result += InliningUtil.compiledCodeSize(m);
-            }
-            return result;
+        public int numberOfMethods() {
+            return concretes.size();
+        }
+
+        @Override
+        public ResolvedJavaMethod methodAt(int index) {
+            assert index >= 0 && index < concretes.size();
+            return concretes.get(index);
         }
 
         @Override
         public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions) {
-            int numberOfMethods = concretes.size();
-            boolean hasReturnValue = invoke.node().kind() != Kind.Void;
-
             // receiver null check must be the first node
             InliningUtil.receiverNullCheck(invoke);
-            if (numberOfMethods > 1 || shouldFallbackToInvoke()) {
-                inlineMultipleMethods(graph, callback, assumptions, numberOfMethods, hasReturnValue);
+            if (hasSingleMethod()) {
+                inlineSingleMethod(graph, callback, assumptions);
             } else {
-                inlineSingleMethod(graph, callback, assumptions);
+                inlineMultipleMethods(graph, callback, assumptions);
             }
         }
 
+        private boolean hasSingleMethod() {
+            return concretes.size() == 1 && !shouldFallbackToInvoke();
+        }
+
         private boolean shouldFallbackToInvoke() {
             return notRecordedTypeProbability > 0;
         }
 
-        private void inlineMultipleMethods(StructuredGraph graph, InliningCallback callback, Assumptions assumptions, int numberOfMethods, boolean hasReturnValue) {
+        private void inlineMultipleMethods(StructuredGraph graph, InliningCallback callback, Assumptions assumptions) {
+            int numberOfMethods = concretes.size();
             FixedNode continuation = invoke.next();
 
             ValueNode originalReceiver = invoke.methodCallTarget().receiver();
@@ -410,7 +439,7 @@
             returnMerge.setStateAfter(invoke.stateAfter().duplicate(invoke.stateAfter().bci));
 
             PhiNode returnValuePhi = null;
-            if (hasReturnValue) {
+            if (invoke.node().kind() != Kind.Void) {
                 returnValuePhi = graph.unique(new PhiNode(invoke.node().kind(), returnMerge));
             }
 
@@ -465,16 +494,13 @@
             assert invoke.node().isAlive();
 
             // replace the invoke with a switch on the type of the actual receiver
-            Kind hubKind = invoke.methodCallTarget().targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind();
-            LoadHubNode receiverHub = graph.add(new LoadHubNode(invoke.methodCallTarget().receiver(), hubKind));
-            graph.addBeforeFixed(invoke.node(), receiverHub);
-            FixedNode dispatchOnType = createDispatchOnType(graph, receiverHub, successors);
+            createDispatchOnTypeBeforeInvoke(graph, successors, false);
 
             assert invoke.next() == continuation;
             invoke.setNext(null);
             returnMerge.setNext(continuation);
             invoke.node().replaceAtUsages(returnValuePhi);
-            invoke.node().replaceAndDelete(dispatchOnType);
+            invoke.node().replaceAndDelete(null);
 
             ArrayList<PiNode> replacements = new ArrayList<>();
 
@@ -544,46 +570,52 @@
             return commonType;
         }
 
+        private ResolvedJavaType getLeastCommonType() {
+            ResolvedJavaType result = getLeastCommonType(0);
+            for (int i = 1; i < concretes.size(); i++) {
+                result = result.findLeastCommonAncestor(getLeastCommonType(i));
+            }
+            return result;
+        }
+
         private void inlineSingleMethod(StructuredGraph graph, InliningCallback callback, Assumptions assumptions) {
             assert concretes.size() == 1 && ptypes.size() > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0;
 
             BeginNode calleeEntryNode = graph.add(new BeginNode());
             calleeEntryNode.setProbability(invoke.probability());
-            Kind hubKind = invoke.methodCallTarget().targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind();
-            LoadHubNode receiverHub = graph.add(new LoadHubNode(invoke.methodCallTarget().receiver(), hubKind));
-            graph.addBeforeFixed(invoke.node(), receiverHub);
 
-            BeginNode unknownTypeSux = BeginNode.begin(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated)));
+            BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
             BeginNode[] successors = new BeginNode[]{calleeEntryNode, unknownTypeSux};
-            FixedNode dispatchOnType = createDispatchOnType(graph, receiverHub, successors);
+            createDispatchOnTypeBeforeInvoke(graph, successors, false);
 
-            FixedWithNextNode pred = (FixedWithNextNode) invoke.node().predecessor();
-            pred.setNext(dispatchOnType);
             calleeEntryNode.setNext(invoke.node());
 
             ResolvedJavaMethod concrete = concretes.get(0);
             inline(invoke, concrete, callback, assumptions, false);
         }
 
-        private FixedNode createDispatchOnType(StructuredGraph graph, LoadHubNode hub, BeginNode[] successors) {
+        private void createDispatchOnTypeBeforeInvoke(StructuredGraph graph, BeginNode[] successors, boolean invokeIsOnlySuccessor) {
             assert ptypes.size() > 1;
 
+            Kind hubKind = invoke.methodCallTarget().targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind();
+            LoadHubNode hub = graph.add(new LoadHubNode(invoke.methodCallTarget().receiver(), hubKind));
+            graph.addBeforeFixed(invoke.node(), hub);
+
             ResolvedJavaType[] keys = new ResolvedJavaType[ptypes.size()];
             double[] keyProbabilities = new double[ptypes.size() + 1];
             int[] keySuccessors = new int[ptypes.size() + 1];
             for (int i = 0; i < ptypes.size(); i++) {
                 keys[i] = ptypes.get(i).getType();
                 keyProbabilities[i] = ptypes.get(i).getProbability();
-                keySuccessors[i] = typesToConcretes[i];
+                keySuccessors[i] = invokeIsOnlySuccessor ? 0 : typesToConcretes[i];
                 assert keySuccessors[i] < successors.length - 1 : "last successor is the unknownTypeSux";
             }
             keyProbabilities[keyProbabilities.length - 1] = notRecordedTypeProbability;
             keySuccessors[keySuccessors.length - 1] = successors.length - 1;
 
-            double[] successorProbabilities = SwitchNode.successorProbabilites(successors.length, keySuccessors, keyProbabilities);
-            TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(hub, successors, successorProbabilities, keys, keyProbabilities, keySuccessors));
-
-            return typeSwitch;
+            TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(hub, successors, keys, keyProbabilities, keySuccessors));
+            FixedWithNextNode pred = (FixedWithNextNode) invoke.node().predecessor();
+            pred.setNext(typeSwitch);
         }
 
         private static BeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, MergeNode exceptionMerge, PhiNode exceptionObjectPhi,
@@ -646,6 +678,56 @@
         }
 
         @Override
+        public void tryToDevirtualizeInvoke(StructuredGraph graph, GraalCodeCacheProvider runtime, Assumptions assumptions) {
+            if (hasSingleMethod()) {
+                tryToDevirtualizeSingleMethod(graph);
+            } else {
+                tryToDevirtualizeMultipleMethods(graph);
+            }
+        }
+
+        private void tryToDevirtualizeSingleMethod(StructuredGraph graph) {
+            devirtualizeWithTypeSwitch(graph, InvokeKind.Special, concretes.get(0));
+        }
+
+        private void tryToDevirtualizeMultipleMethods(StructuredGraph graph) {
+            MethodCallTargetNode methodCallTarget = invoke.methodCallTarget();
+            if (methodCallTarget.invokeKind() == InvokeKind.Interface) {
+                ResolvedJavaMethod targetMethod = methodCallTarget.targetMethod();
+                ResolvedJavaType leastCommonType = getLeastCommonType();
+                // check if we have a common base type that implements the interface -> in that case
+// we have a vtable entry for the interface method and can use a less expensive virtual call
+                if (!leastCommonType.isInterface() && targetMethod.getDeclaringClass().isAssignableFrom(leastCommonType)) {
+                    ResolvedJavaMethod baseClassTargetMethod = leastCommonType.resolveMethod(targetMethod);
+                    if (baseClassTargetMethod != null) {
+                        devirtualizeWithTypeSwitch(graph, InvokeKind.Virtual, leastCommonType.resolveMethod(targetMethod));
+                    }
+                }
+            }
+        }
+
+        private void devirtualizeWithTypeSwitch(StructuredGraph graph, InvokeKind kind, ResolvedJavaMethod target) {
+            InliningUtil.receiverNullCheck(invoke);
+
+            BeginNode invocationEntry = graph.add(new BeginNode());
+            invocationEntry.setProbability(invoke.probability());
+
+            BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
+            BeginNode[] successors = new BeginNode[]{invocationEntry, unknownTypeSux};
+            createDispatchOnTypeBeforeInvoke(graph, successors, true);
+
+            invocationEntry.setNext(invoke.node());
+            ValueNode receiver = invoke.methodCallTarget().receiver();
+            PiNode anchoredReceiver = createAnchoredReceiver(graph, invocationEntry, target.getDeclaringClass(), receiver, false);
+            invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver);
+            replaceInvokeCallTarget(graph, kind, target);
+        }
+
+        private static BeginNode createUnknownTypeSuccessor(StructuredGraph graph) {
+            return BeginNode.begin(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated)));
+        }
+
+        @Override
         public String toString() {
             StringBuilder builder = new StringBuilder(shouldFallbackToInvoke() ? "megamorphic" : "polymorphic");
             builder.append(", ");
@@ -675,8 +757,8 @@
 
         private final Assumption takenAssumption;
 
-        public AssumptionInlineInfo(Invoke invoke, double weight, ResolvedJavaMethod concrete, Assumption takenAssumption) {
-            super(invoke, weight, concrete);
+        public AssumptionInlineInfo(Invoke invoke, ResolvedJavaMethod concrete, Assumption takenAssumption) {
+            super(invoke, concrete);
             this.takenAssumption = takenAssumption;
         }
 
@@ -689,6 +771,12 @@
         }
 
         @Override
+        public void tryToDevirtualizeInvoke(StructuredGraph graph, GraalCodeCacheProvider runtime, Assumptions assumptions) {
+            assumptions.record(takenAssumption);
+            replaceInvokeCallTarget(graph, InvokeKind.Special, concrete);
+        }
+
+        @Override
         public String toString() {
             return "assumption " + MetaUtil.format("%H.%n(%p):%r", concrete);
         }
@@ -698,10 +786,9 @@
      * Determines if inlining is possible at the given invoke node.
      * 
      * @param invoke the invoke that should be inlined
-     * @param inliningPolicy used to determine the weight of a specific inlining
      * @return an instance of InlineInfo, or null if no inlining is possible at the given invoke
      */
-    public static InlineInfo getInlineInfo(Invoke invoke, Assumptions assumptions, InliningPolicy inliningPolicy, OptimisticOptimizations optimisticOpts) {
+    public static InlineInfo getInlineInfo(Invoke invoke, Assumptions assumptions, OptimisticOptimizations optimisticOpts) {
         if (!checkInvokeConditions(invoke)) {
             return null;
         }
@@ -710,7 +797,7 @@
         ResolvedJavaMethod targetMethod = callTarget.targetMethod();
 
         if (callTarget.invokeKind() == InvokeKind.Special || targetMethod.canBeStaticallyBound()) {
-            return getExactInlineInfo(invoke, inliningPolicy, optimisticOpts, caller, targetMethod);
+            return getExactInlineInfo(invoke, optimisticOpts, targetMethod);
         }
 
         assert callTarget.invokeKind() == InvokeKind.Virtual || callTarget.invokeKind() == InvokeKind.Interface;
@@ -725,57 +812,49 @@
                 holder = receiverType;
                 if (receiverStamp.isExactType()) {
                     assert targetMethod.getDeclaringClass().isAssignableFrom(holder) : holder + " subtype of " + targetMethod.getDeclaringClass() + " for " + targetMethod;
-                    return getExactInlineInfo(invoke, inliningPolicy, optimisticOpts, caller, holder.resolveMethod(targetMethod));
+                    return getExactInlineInfo(invoke, optimisticOpts, holder.resolveMethod(targetMethod));
                 }
             }
         }
 
         if (holder.isArray()) {
             // arrays can be treated as Objects
-            return getExactInlineInfo(invoke, inliningPolicy, optimisticOpts, caller, holder.resolveMethod(targetMethod));
+            return getExactInlineInfo(invoke, optimisticOpts, holder.resolveMethod(targetMethod));
         }
 
-        // TODO (chaeubl): we could also use the type determined after assumptions for the
-        // type-checked inlining case as it might have an effect on type filtering
         if (assumptions.useOptimisticAssumptions()) {
             ResolvedJavaType uniqueSubtype = holder.findUniqueConcreteSubtype();
             if (uniqueSubtype != null) {
-                return getAssumptionInlineInfo(invoke, inliningPolicy, optimisticOpts, caller, uniqueSubtype.resolveMethod(targetMethod), new Assumptions.ConcreteSubtype(holder, uniqueSubtype));
+                return getAssumptionInlineInfo(invoke, optimisticOpts, uniqueSubtype.resolveMethod(targetMethod), new Assumptions.ConcreteSubtype(holder, uniqueSubtype));
             }
 
             ResolvedJavaMethod concrete = holder.findUniqueConcreteMethod(targetMethod);
             if (concrete != null) {
-                return getAssumptionInlineInfo(invoke, inliningPolicy, optimisticOpts, caller, concrete, new Assumptions.ConcreteMethod(targetMethod, holder, concrete));
+                return getAssumptionInlineInfo(invoke, optimisticOpts, concrete, new Assumptions.ConcreteMethod(targetMethod, holder, concrete));
             }
-
-            // TODO (chaeubl): C1 has one more assumption in the case of interfaces
         }
 
         // type check based inlining
-        return getTypeCheckedInlineInfo(invoke, inliningPolicy, caller, holder, targetMethod, optimisticOpts);
+        return getTypeCheckedInlineInfo(invoke, caller, holder, targetMethod, optimisticOpts);
     }
 
-    private static InlineInfo getAssumptionInlineInfo(Invoke invoke, InliningPolicy inliningPolicy, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod caller, ResolvedJavaMethod concrete,
-                    Assumption takenAssumption) {
+    private static InlineInfo getAssumptionInlineInfo(Invoke invoke, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod concrete, Assumption takenAssumption) {
         assert !Modifier.isAbstract(concrete.getModifiers());
         if (!checkTargetConditions(invoke, concrete, optimisticOpts)) {
             return null;
         }
-        double weight = inliningPolicy.inliningWeight(caller, concrete, invoke);
-        return new AssumptionInlineInfo(invoke, weight, concrete, takenAssumption);
+        return new AssumptionInlineInfo(invoke, concrete, takenAssumption);
     }
 
-    private static InlineInfo getExactInlineInfo(Invoke invoke, InliningPolicy inliningPolicy, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod caller, ResolvedJavaMethod targetMethod) {
+    private static InlineInfo getExactInlineInfo(Invoke invoke, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod targetMethod) {
         assert !Modifier.isAbstract(targetMethod.getModifiers());
         if (!checkTargetConditions(invoke, targetMethod, optimisticOpts)) {
             return null;
         }
-        double weight = inliningPolicy.inliningWeight(caller, targetMethod, invoke);
-        return new ExactInlineInfo(invoke, weight, targetMethod);
+        return new ExactInlineInfo(invoke, targetMethod);
     }
 
-    private static InlineInfo getTypeCheckedInlineInfo(Invoke invoke, InliningPolicy inliningPolicy, ResolvedJavaMethod caller, ResolvedJavaType holder, ResolvedJavaMethod targetMethod,
-                    OptimisticOptimizations optimisticOpts) {
+    private static InlineInfo getTypeCheckedInlineInfo(Invoke invoke, ResolvedJavaMethod caller, ResolvedJavaType holder, ResolvedJavaMethod targetMethod, OptimisticOptimizations optimisticOpts) {
         ProfilingInfo profilingInfo = caller.getProfilingInfo();
         JavaTypeProfile typeProfile = profilingInfo.getTypeProfile(invoke.bci());
         if (typeProfile == null) {
@@ -799,8 +878,7 @@
             if (!checkTargetConditions(invoke, concrete, optimisticOpts)) {
                 return null;
             }
-            double weight = inliningPolicy.inliningWeight(caller, concrete, invoke);
-            return new TypeGuardInlineInfo(invoke, weight, concrete, type);
+            return new TypeGuardInlineInfo(invoke, concrete, type);
         } else {
             invoke.setPolymorphic(true);
 
@@ -814,14 +892,6 @@
                                 notRecordedTypeProbability * 100);
             }
 
-            // TODO (chaeubl) inlining of multiple methods should work differently
-            // 1. check which methods can be inlined
-            // 2. for those methods, use weight and probability to compute which of them should be
-            // inlined
-            // 3. do the inlining
-            // a) all seen methods can be inlined -> do so and guard with deopt
-            // b) some methods can be inlined -> inline them and fall back to invocation if violated
-
             // determine concrete methods and map type to specific method
             ArrayList<ResolvedJavaMethod> concreteMethods = new ArrayList<>();
             int[] typesToConcretes = new int[ptypes.size()];
@@ -836,14 +906,12 @@
                 typesToConcretes[i] = index;
             }
 
-            double totalWeight = 0;
             for (ResolvedJavaMethod concrete : concreteMethods) {
                 if (!checkTargetConditions(invoke, concrete, optimisticOpts)) {
                     return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "it is a polymorphic method call and at least one invoked method cannot be inlined");
                 }
-                totalWeight += inliningPolicy.inliningWeight(caller, concrete, invoke);
             }
-            return new MultiTypeGuardInlineInfo(invoke, totalWeight, concreteMethods, ptypes, typesToConcretes, notRecordedTypeProbability);
+            return new MultiTypeGuardInlineInfo(invoke, concreteMethods, ptypes, typesToConcretes, notRecordedTypeProbability);
         }
     }
 
@@ -1034,7 +1102,7 @@
                 if (node instanceof Invoke) {
                     Invoke newInvoke = (Invoke) node;
                     double newRelevance = newInvoke.inliningRelevance() * invoke.inliningRelevance();
-                    if (GraalOptions.LimitInlinedProbability) {
+                    if (GraalOptions.LimitInlinedRelevance) {
                         newRelevance = Math.min(newRelevance, invoke.inliningRelevance());
                     }
                     newInvoke.setInliningRelevance(newRelevance);
@@ -1106,14 +1174,6 @@
         return (StructuredGraph) target.getCompilerStorage().get(Graph.class);
     }
 
-    private static int compiledCodeSize(ResolvedJavaMethod target) {
-        if (GraalOptions.AlwaysInlineIntrinsics && canIntrinsify(target)) {
-            return 0;
-        } else {
-            return target.getCompiledCodeSize();
-        }
-    }
-
     public static Class<? extends FixedWithNextNode> getMacroNodeClass(ResolvedJavaMethod target) {
         Object result = target.getCompilerStorage().get(Node.class);
         return result == null ? null : ((Class<?>) result).asSubclass(FixedWithNextNode.class);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Mon Feb 11 10:41:29 2013 +0100
@@ -46,7 +46,7 @@
     @Override
     protected void run(StructuredGraph graph) {
         Set<Node> canonicalizationRoots = new HashSet<>();
-        ConditionalEliminationPhase eliminate = new ConditionalEliminationPhase();
+        ConditionalEliminationPhase eliminate = new ConditionalEliminationPhase(runtime);
         Listener listener = new Listener(canonicalizationRoots);
         while (true) {
             graph.trackInputChange(listener);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Mon Feb 11 10:41:29 2013 +0100
@@ -43,30 +43,24 @@
            static boolean InlineMonomorphicCalls             = true;
            static boolean InlinePolymorphicCalls             = true;
            static boolean InlineMegamorphicCalls             = ____;
-    public static int     InliningPolicy                     = 1;
-    public static int     InliningDecision                   = 4;
-    public static int     WeightComputationPolicy            = 2;
-    public static int     MaximumTrivialSize                 = 10;
     public static int     MaximumInlineLevel                 = 30;
-    public static int     MaximumDesiredSize                 = 3000;
+    public static int     MaximumDesiredSize                 = 5000;
     public static int     MaximumRecursiveInlining           = 1;
-    public static int     SmallCompiledCodeSize              = 2200;
     public static boolean LimitInlinedProbability            = ____;
-    public static boolean UseRelevanceBasedInlining          = ____;
-    // WeightBasedInliningPolicy (0)
-    public static float   InliningSizePenaltyExp             = 20;
-    public static float   MaximumInlineWeight                = 1.25f;
-    public static float   InliningSizePenalty                = 1;
-    // StaticSizeBasedInliningPolicy (1), MinimumCodeSizeBasedInlining (2),
-    // DynamicSizeBasedInliningPolicy (3)
-    public static int     MaximumInlineSize                  = 35;
-    // GreedySizeBasedInlining (4)
-    public static int     MaximumGreedyInlineSize            = 100;
-    public static int     InliningBonusPerTransferredValue   = 10;
-    // Common options for inlining policies 1 to 4
-    public static float   NestedInliningSizeRatio            = 1f;
+    public static boolean LimitInlinedRelevance              = true;
     public static float   BoostInliningForEscapeAnalysis     = 2f;
-    public static float   RatioCapForInlining                = 1f;
+    public static float   RelevanceCapForInlining            = 1f;
+
+    public static int     TrivialBytecodeSize                = 10;
+    public static int     NormalBytecodeSize                 = 150;
+    public static int     MaximumBytecodeSize                = 500;
+    public static int     TrivialComplexity                  = 10;
+    public static int     NormalComplexity                   = 60;
+    public static int     MaximumComplexity                  = 400;
+    public static int     TrivialCompiledCodeSize            = 150;
+    public static int     NormalCompiledCodeSize             = 750;
+    public static int     MaximumCompiledCodeSize            = 4000;
+    public static int     SmallCompiledCodeSize              = 1000;
 
     // escape analysis settings
     public static boolean PartialEscapeAnalysis              = true;
@@ -80,7 +74,6 @@
 
     // absolute probability analysis
     public static boolean ProbabilityAnalysis                = true;
-    public static int     LoopFrequencyPropagationPolicy     = -2;
 
     // profiling information
     public static int     DeoptsToDisableOptimisticOptimization = 40;
@@ -113,7 +106,7 @@
     public static int     LoopUnswitchUncertaintyBoost       = 5;
 
     // debugging settings
-    public static int     MethodEndBreakpointGuards          = 0;
+    public static int     MethodEndBreakpointGuards          = 2;
     public static boolean ZapStackOnMethodEntry              = ____;
     public static boolean DeoptALot                          = ____;
     public static boolean VerifyPhases                       = true;
@@ -172,7 +165,7 @@
     public static boolean AlwaysInlineVTableStubs            = ____;
     public static boolean GenAssertionCode                   = ____;
     public static boolean AlignCallsForPatching              = true;
-    public static boolean ResolveClassBeforeStaticInvoke     = true;
+    public static boolean ResolveClassBeforeStaticInvoke     = ____;
     public static boolean CanOmitFrame                       = true;
     public static int     SafepointPollOffset                = 256;
 
@@ -201,6 +194,7 @@
     public static boolean OptTailDuplication                 = true;
     public static boolean OptEliminatePartiallyRedundantGuards = true;
     public static boolean OptFilterProfiledTypes             = true;
+    public static boolean OptDevirtualizeInvokesOptimistically = true;
 
     // Intrinsification settings
     public static boolean IntrinsifyArrayCopy                = true;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Mon Feb 11 10:41:29 2013 +0100
@@ -52,9 +52,10 @@
         if (checkDeoptimizations(method.getProfilingInfo(), deoptReason)) {
             enabledOpts.add(optimization);
         } else {
-            // TODO (chaeubl): change to Debug.log when we are sure that optimistic optimizations
-            // are not disabled
-            // unnecessarily
+            /*
+             * TODO (chaeubl): see GRAAL-75 (remove when we are sure that optimistic optimizations
+             * are not disabled unnecessarily
+             */
             TTY.println("WARN: deactivated optimistic optimization %s for %s", optimization.name(), MetaUtil.format("%H.%n(%p)", method));
             disabledOptimisticOptsMetric.increment();
         }
@@ -84,6 +85,10 @@
         return GraalOptions.InlineMegamorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
     }
 
+    public boolean devirtualizeInvokes() {
+        return GraalOptions.OptDevirtualizeInvokesOptimistically && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
+    }
+
     public boolean useExceptionProbability() {
         return GraalOptions.UseExceptionProbability && enabledOpts.contains(Optimization.UseExceptionProbability);
     }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java	Mon Feb 11 10:41:29 2013 +0100
@@ -30,15 +30,13 @@
 
 public abstract class ScopedPostOrderNodeIterator {
 
-    private final NodeBitMap processedNodes;
     private final Deque<FixedNode> nodeQueue;
     private final NodeBitMap queuedNodes;
     private final Deque<FixedNode> scopes;
 
-    protected FixedNode currentScope;
+    protected FixedNode currentScopeStart;
 
     public ScopedPostOrderNodeIterator(StructuredGraph graph) {
-        this.processedNodes = graph.createNodeBitMap();
         this.queuedNodes = graph.createNodeBitMap();
         this.nodeQueue = new ArrayDeque<>();
         this.scopes = getScopes(graph);
@@ -46,64 +44,57 @@
 
     public void apply() {
         while (!scopes.isEmpty()) {
-            processedNodes.clearAll();
             queuedNodes.clearAll();
-            this.currentScope = scopes.pop();
+            this.currentScopeStart = scopes.pop();
             initializeScope();
             processScope();
         }
     }
 
     public void processScope() {
-        FixedNode current = currentScope;
-        do {
+        FixedNode current;
+        queue(currentScopeStart);
+
+        while ((current = nextQueuedNode()) != null) {
             assert current.isAlive();
-            processedNodes.mark(current);
 
             if (current instanceof Invoke) {
                 invoke((Invoke) current);
                 queueSuccessors(current);
-                current = nextQueuedNode();
             } else if (current instanceof LoopBeginNode) {
                 queueLoopBeginSuccessors((LoopBeginNode) current);
-                current = nextQueuedNode();
             } else if (current instanceof LoopExitNode) {
                 queueLoopExitSuccessors((LoopExitNode) current);
-                current = nextQueuedNode();
             } else if (current instanceof LoopEndNode) {
-                current = nextQueuedNode();
+                // nothing todo
             } else if (current instanceof MergeNode) {
-                current = ((MergeNode) current).next();
-                assert current != null;
+                queueSuccessors(current);
             } else if (current instanceof FixedWithNextNode) {
                 queueSuccessors(current);
-                current = nextQueuedNode();
             } else if (current instanceof EndNode) {
                 queueMerge((EndNode) current);
-                current = nextQueuedNode();
             } else if (current instanceof DeoptimizeNode) {
-                current = nextQueuedNode();
+                // nothing todo
             } else if (current instanceof ReturnNode) {
-                current = nextQueuedNode();
+                // nothing todo
             } else if (current instanceof UnwindNode) {
-                current = nextQueuedNode();
+                // nothing todo
             } else if (current instanceof ControlSplitNode) {
                 queueSuccessors(current);
-                current = nextQueuedNode();
             } else {
                 assert false : current;
             }
-        } while (current != null);
+        }
     }
 
     protected void queueLoopBeginSuccessors(LoopBeginNode node) {
-        if (currentScope == node) {
+        if (currentScopeStart == node) {
             queue(node.next());
-        } else if (currentScope instanceof LoopBeginNode) {
+        } else if (currentScopeStart instanceof LoopBeginNode) {
             // so we are currently processing loop A and found another loop B
             // -> queue all loop exits of B except those that also exit loop A
             for (LoopExitNode loopExit : node.loopExits()) {
-                if (!((LoopBeginNode) currentScope).loopExits().contains(loopExit)) {
+                if (!((LoopBeginNode) currentScopeStart).loopExits().contains(loopExit)) {
                     queue(loopExit);
                 }
             }
@@ -113,7 +104,7 @@
     }
 
     protected void queueLoopExitSuccessors(LoopExitNode node) {
-        if (!(currentScope instanceof LoopBeginNode) || !((LoopBeginNode) currentScope).loopExits().contains(node)) {
+        if (!(currentScopeStart instanceof LoopBeginNode) || !((LoopBeginNode) currentScopeStart).loopExits().contains(node)) {
             queueSuccessors(node);
         }
     }
@@ -157,14 +148,13 @@
     private void queueMerge(EndNode end) {
         MergeNode merge = end.merge();
         if (!queuedNodes.isMarked(merge) && visitedAllEnds(merge)) {
-            queuedNodes.mark(merge);
-            nodeQueue.add(merge);
+            queue(merge);
         }
     }
 
     private boolean visitedAllEnds(MergeNode merge) {
         for (int i = 0; i < merge.forwardEndCount(); i++) {
-            if (!processedNodes.isMarked(merge.forwardEndAt(i))) {
+            if (!queuedNodes.isMarked(merge.forwardEndAt(i))) {
                 return false;
             }
         }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java	Mon Feb 11 10:41:29 2013 +0100
@@ -172,7 +172,7 @@
                 // Can simply use the phi result if the same materialized values are expected.
                 return result;
             } else {
-                return MaterializeNode.create(asCondition(trueValue), t, f);
+                return t.graph().unique(new ConditionalNode(asCondition(trueValue), t, f));
             }
         }
     }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSubstitutions.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSubstitutions.java	Mon Feb 11 10:41:29 2013 +0100
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.snippets;
 
-import static com.oracle.graal.nodes.MaterializeNode.*;
+import static com.oracle.graal.nodes.calc.ConditionalNode.*;
 import static com.oracle.graal.nodes.calc.Condition.*;
 
 import com.oracle.graal.api.code.*;
@@ -38,12 +38,12 @@
 
     @MethodSubstitution
     public static boolean aboveThan(int a, int b) {
-        return materialize(BT, b, a);
+        return materializeCondition(BT, b, a);
     }
 
     @MethodSubstitution
     public static boolean aboveOrEqual(int a, int b) {
-        return !materialize(BT, a, b);
+        return !materializeCondition(BT, a, b);
     }
 
     /**
@@ -51,7 +51,7 @@
      */
     @MethodSubstitution
     public static boolean belowThan(int a, int b) {
-        return materialize(BT, a, b);
+        return materializeCondition(BT, a, b);
     }
 
     /**
@@ -59,7 +59,7 @@
      */
     @MethodSubstitution
     public static boolean belowOrEqual(int a, int b) {
-        return !materialize(BT, b, a);
+        return !materializeCondition(BT, b, a);
     }
 
     /**
@@ -67,7 +67,7 @@
      */
     @MethodSubstitution
     public static boolean aboveThan(long a, long b) {
-        return materialize(BT, b, a);
+        return materializeCondition(BT, b, a);
     }
 
     /**
@@ -75,7 +75,7 @@
      */
     @MethodSubstitution
     public static boolean aboveOrEqual(long a, long b) {
-        return !materialize(BT, a, b);
+        return !materializeCondition(BT, a, b);
     }
 
     /**
@@ -83,7 +83,7 @@
      */
     @MethodSubstitution
     public static boolean belowThan(long a, long b) {
-        return materialize(BT, a, b);
+        return materializeCondition(BT, a, b);
     }
 
     /**
@@ -91,7 +91,7 @@
      */
     @MethodSubstitution
     public static boolean belowOrEqual(long a, long b) {
-        return !materialize(BT, b, a);
+        return !materializeCondition(BT, b, a);
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Mon Feb 11 10:41:29 2013 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.sparc;
+
+import static com.oracle.graal.api.code.MemoryBarriers.*;
+
+import java.nio.*;
+
+import com.oracle.graal.api.code.*;
+
+/**
+ * Represents the SPARC architecture.
+ */
+public class SPARC extends Architecture {
+
+    // SPARC: Define registers.
+
+    public SPARC() {
+        super("AMD64", 8, ByteOrder.LITTLE_ENDIAN, null, LOAD_STORE | STORE_STORE, 1, 0, 8);
+        // SPARC: Fix architecture parameters.
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalTest.java	Mon Feb 11 10:41:29 2013 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, 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.test;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+/**
+ * Base class for Graal tests.
+ * <p>
+ * This contains common utility methods that are used in multiple test projects.
+ */
+public class GraalTest {
+
+    protected Method getMethod(String methodName) {
+        Method found = null;
+        for (Method m : this.getClass().getMethods()) {
+            if (m.getName().equals(methodName)) {
+                Assert.assertNull(found);
+                found = m;
+            }
+        }
+        if (found != null) {
+            return found;
+        } else {
+            throw new RuntimeException("method not found: " + methodName);
+        }
+    }
+}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java	Mon Feb 11 10:41:29 2013 +0100
@@ -94,12 +94,7 @@
             VirtualArrayNode virtual = (VirtualArrayNode) virtualObject;
 
             ResolvedJavaType element = virtual.componentType();
-            NewArrayNode newArray;
-            if (element.getKind() == Kind.Object) {
-                newArray = graph.add(new NewObjectArrayNode(element, ConstantNode.forInt(virtual.entryCount(), graph), defaultValuesOnly, lockCount > 0));
-            } else {
-                newArray = graph.add(new NewPrimitiveArrayNode(element, ConstantNode.forInt(virtual.entryCount(), graph), defaultValuesOnly, lockCount > 0));
-            }
+            NewArrayNode newArray = graph.add(new NewArrayNode(element, ConstantNode.forInt(virtual.entryCount(), graph), defaultValuesOnly, lockCount > 0));
             this.replaceAtUsages(newArray);
             graph.addBeforeFixed(this, newArray);
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Mon Feb 11 10:41:29 2013 +0100
@@ -26,7 +26,6 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.virtual.nodes.*;
@@ -62,7 +61,7 @@
      * 
      * @param node The floating node to be added.
      */
-    public void addFloatingNode(final FloatingNode node) {
+    public void addFloatingNode(final ValueNode node) {
         add(new Effect() {
 
             @Override
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Mon Feb 11 10:41:29 2013 +0100
@@ -95,7 +95,7 @@
                     PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, runtime);
                     ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock(), new BlockState(), null);
 
-                    if (closure.getVirtualIdCount() == 0) {
+                    if (closure.getNewVirtualObjectCount() == 0) {
                         return false;
                     }
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Mon Feb 11 10:41:29 2013 +0100
@@ -69,8 +69,8 @@
         return effects;
     }
 
-    public int getVirtualIdCount() {
-        return tool.getNextVirtualId();
+    public int getNewVirtualObjectCount() {
+        return tool.getNewVirtualObjectCount();
     }
 
     @Override
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Mon Feb 11 10:41:29 2013 +0100
@@ -49,7 +49,7 @@
     private boolean customAction;
     private BlockState state;
     private ValueNode current;
-    private int virtualIds = 0;
+    private int newVirtualObjectCount = 0;
 
     @Override
     public MetaAccessProvider getMetaAccessProvider() {
@@ -71,9 +71,8 @@
         return customAction;
     }
 
-    @Override
-    public int getNextVirtualId() {
-        return virtualIds;
+    public int getNewVirtualObjectCount() {
+        return newVirtualObjectCount;
     }
 
     @Override
@@ -156,7 +155,7 @@
         state.addObject(virtualObject, new ObjectState(virtualObject, entryState, EscapeState.Virtual, lockCount));
         state.addAndMarkAlias(virtualObject, virtualObject, usages);
         PartialEscapeClosure.METRIC_ALLOCATION_REMOVED.increment();
-        virtualIds++;
+        newVirtualObjectCount++;
     }
 
     @Override
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Signed.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Signed.java	Mon Feb 11 10:41:29 2013 +0100
@@ -119,6 +119,22 @@
      * Compares this Signed with the specified value.
      * 
      * @param val value to which this Signed is to be compared.
+     * @return {@code this == val}
+     */
+    boolean equal(Signed val);
+
+    /**
+     * Compares this Signed with the specified value.
+     * 
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this != val}
+     */
+    boolean notEqual(Signed val);
+
+    /**
+     * Compares this Signed with the specified value.
+     * 
+     * @param val value to which this Signed is to be compared.
      * @return {@code this < val}
      */
     boolean lessThan(Signed val);
@@ -234,6 +250,22 @@
      * Compares this Signed with the specified value.
      * 
      * @param val value to which this Signed is to be compared.
+     * @return {@code this == val}
+     */
+    boolean equal(int val);
+
+    /**
+     * Compares this Signed with the specified value.
+     * 
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this != val}
+     */
+    boolean notEqual(int val);
+
+    /**
+     * Compares this Signed with the specified value.
+     * 
+     * @param val value to which this Signed is to be compared.
      * @return {@code this < val}
      */
     boolean lessThan(int val);
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Unsigned.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Unsigned.java	Mon Feb 11 10:41:29 2013 +0100
@@ -115,6 +115,22 @@
      * Compares this Unsigned with the specified value.
      * 
      * @param val value to which this Unsigned is to be compared.
+     * @return {@code this == val}
+     */
+    boolean equal(Unsigned val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     * 
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this != val}
+     */
+    boolean notEqual(Unsigned val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     * 
+     * @param val value to which this Unsigned is to be compared.
      * @return {@code this < val}
      */
     boolean belowThan(Unsigned val);
@@ -260,6 +276,28 @@
      * Therefore, the result is only well-defined for positive right operands.
      * 
      * @param val value to which this Unsigned is to be compared.
+     * @return {@code this == val}
+     */
+    boolean equal(int val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     * 
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this != val}
+     */
+    boolean notEqual(int val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     * 
+     * @param val value to which this Unsigned is to be compared.
      * @return {@code this < val}
      */
     boolean belowThan(int val);
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Mon Feb 11 10:41:29 2013 +0100
@@ -25,9 +25,9 @@
 import static com.oracle.graal.graph.UnsafeAccess.*;
 
 import java.lang.annotation.*;
-import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 
@@ -415,6 +415,52 @@
     }
 
     @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
+    public boolean equal(Signed val) {
+        return equal((Word) val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
+    public boolean equal(Unsigned val) {
+        return equal((Word) val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
+    public boolean equal(int val) {
+        return equal(intParam(val));
+    }
+
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
+    public boolean equal(Word val) {
+        return unbox() == val.unbox();
+    }
+
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
+    public boolean notEqual(Signed val) {
+        return notEqual((Word) val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
+    public boolean notEqual(Unsigned val) {
+        return notEqual((Word) val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
+    public boolean notEqual(int val) {
+        return notEqual(intParam(val));
+    }
+
+    @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
+    public boolean notEqual(Word val) {
+        return unbox() != val.unbox();
+    }
+
+    @Override
     @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT)
     public boolean lessThan(Signed val) {
         return lessThan((Word) val);
@@ -815,6 +861,21 @@
     public void writeObject(int offset, Object val) {
         writeObject(signed(offset), val);
     }
+
+    @Override
+    public final boolean equals(Object obj) {
+        throw GraalInternalError.shouldNotReachHere("equals must not be called on words");
+    }
+
+    @Override
+    public final int hashCode() {
+        throw GraalInternalError.shouldNotReachHere("hashCode must not be called on words");
+    }
+
+    @Override
+    public String toString() {
+        throw GraalInternalError.shouldNotReachHere("toString must not be called on words");
+    }
 }
 
 final class HostedWord extends Word {
@@ -823,7 +884,6 @@
     private static final int SMALL_TO = 100;
 
     private static final HostedWord[] smallCache = new HostedWord[SMALL_TO - SMALL_FROM + 1];
-    private static final ConcurrentHashMap<Long, HostedWord> cache = new ConcurrentHashMap<>();
 
     static {
         for (int i = SMALL_FROM; i <= SMALL_TO; i++) {
@@ -841,18 +901,16 @@
         if (val >= SMALL_FROM && val <= SMALL_TO) {
             return smallCache[(int) val - SMALL_FROM];
         }
-        Long key = val;
-        HostedWord result = cache.get(key);
-        if (result != null) {
-            return result;
-        }
-        HostedWord newValue = new HostedWord(val);
-        HostedWord oldValue = cache.putIfAbsent(key, newValue);
-        return oldValue == null ? newValue : oldValue;
+        return new HostedWord(val);
     }
 
     @Override
     protected long unbox() {
         return rawValue;
     }
+
+    @Override
+    public String toString() {
+        return "Word<" + rawValue + ">";
+    }
 }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Mon Feb 11 10:41:29 2013 +0100
@@ -95,12 +95,13 @@
             if (x.kind() == wordKind || y.kind() == wordKind) {
                 assert x.kind() == wordKind;
                 assert y.kind() == wordKind;
-                graph.replaceFloating(objectEqualsNode, graph.unique(new IntegerEqualsNode(x, y)));
+
+                // TODO Remove the whole iteration of ObjectEqualsNodes when we are sure that there
+                // is no more code where this triggers.
+                throw GraalInternalError.shouldNotReachHere("Comparison of words with == and != is no longer supported");
             }
         }
 
-        // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are
-        // words
         for (LoadIndexedNode load : graph.getNodes().filter(LoadIndexedNode.class).snapshot()) {
             if (isWord(load)) {
                 load.setStamp(StampFactory.forKind(wordKind));
@@ -247,7 +248,7 @@
         } else {
             comparison = new IntegerLessThanNode(a, b);
         }
-        MaterializeNode materialize = MaterializeNode.create(graph.unique(comparison));
+        ConditionalNode materialize = graph.unique(new ConditionalNode(graph.unique(comparison), ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph)));
 
         ValueNode op;
         if (condition.canonicalNegate()) {
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Mon Feb 11 10:41:29 2013 +0100
@@ -97,10 +97,8 @@
                         }
                     }
                 } else if (usage instanceof ObjectEqualsNode) {
-                    ObjectEqualsNode compare = (ObjectEqualsNode) usage;
-                    if (compare.x() == node || compare.y() == node) {
-                        verify(isWord(compare.x()) == isWord(compare.y()), node, compare.usages().first(), "cannot mixed word and non-word type in use of '==' or '!='");
-                    }
+                    verify(!isWord(node) || ((ObjectEqualsNode) usage).x() != node, node, usage, "cannot use word type in comparison");
+                    verify(!isWord(node) || ((ObjectEqualsNode) usage).y() != node, node, usage, "cannot use word type in comparison");
                 } else if (usage instanceof ArrayLengthNode) {
                     verify(!isWord(node) || ((ArrayLengthNode) usage).array() != node, node, usage, "cannot get array length from word value");
                 } else if (usage instanceof PhiNode) {
@@ -148,7 +146,7 @@
             return buf.toString();
         } else {
             String loc = GraphUtil.approxSourceLocation(n);
-            return loc == null ? "<unknown>" : loc;
+            return loc == null ? MetaUtil.format("method %h.%n", ((StructuredGraph) n.graph()).method()) : loc;
         }
     }
 }
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java	Mon Feb 11 10:41:29 2013 +0100
@@ -35,7 +35,7 @@
  * The frame is the preferred data structure for passing values between nodes. It can in particular
  * be used for storing the values of local variables of the guest language. The
  * {@link FrameDescriptor} represents the current structure of the frame. The method
- * {@link FrameDescriptor#addFrameSlot(String, Class)} can be used to create predefined frame slots.
+ * {@link FrameDescriptor#addFrameSlot(Object, Class)} can be used to create predefined frame slots.
  * The setter and getter methods in the {@link Frame} class can be used to access the current value
  * of a particular frame slot.
  * </p>
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Mon Feb 11 10:41:29 2013 +0100
@@ -58,4 +58,20 @@
      * @return the new call target object
      */
     CallTarget createCallTarget(RootNode rootNode, FrameDescriptor frameDescriptor);
+
+    /**
+     * Creates a new materialized frame object that can be used to store values.
+     * 
+     * @return the newly created materialized frame object
+     */
+    MaterializedFrame createMaterializedFrame(Arguments arguments);
+
+    /**
+     * Creates a new materialized frame object with the given frame descriptor that can be used to
+     * store values.
+     * 
+     * @param frameDescriptor the frame descriptor describing this frame's values
+     * @return the newly created materialized frame object
+     */
+    MaterializedFrame createMaterializedFrame(Arguments arguments, FrameDescriptor frameDescriptor);
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java	Mon Feb 11 10:41:29 2013 +0100
@@ -31,6 +31,11 @@
 public interface Frame {
 
     /**
+     * @return the object describing the layout of this frame
+     */
+    FrameDescriptor getFrameDescriptor();
+
+    /**
      * @return the arguments used when calling this method
      */
     Arguments getArguments();
@@ -132,4 +137,23 @@
     void setDouble(FrameSlot slot, double value);
 
     void updateToLatestVersion();
+
+    /**
+     * Converts this virtual frame into a packed frame that has no longer direct access to the local
+     * variables. This packing is an important hint to the Truffle optimizer and therefore passing
+     * around a {@link PackedFrame} should be preferred over passing around a {@link VirtualFrame}
+     * when the probability that an unpacking will occur is low.
+     * 
+     * @return the packed frame
+     */
+    PackedFrame pack();
+
+    /**
+     * Materializes this frame, which allows it to be stored in a field or cast to
+     * {@link java.lang.Object}. The frame however looses the ability to be packed or to access the
+     * caller frame.
+     * 
+     * @return the new materialized frame
+     */
+    MaterializedFrame materialize();
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Mon Feb 11 10:41:29 2013 +0100
@@ -33,7 +33,7 @@
     protected final TypeConversion typeConversion;
     private final ArrayList<FrameSlotImpl> slots;
     private FrameVersionImpl lastVersion;
-    private final HashMap<String, FrameSlotImpl> nameToSlotMap;
+    private final HashMap<Object, FrameSlotImpl> identifierToSlotMap;
 
     public FrameDescriptor() {
         this(DefaultTypeConversion.getInstance());
@@ -42,32 +42,32 @@
     public FrameDescriptor(TypeConversion typeConversion) {
         this.typeConversion = typeConversion;
         slots = new ArrayList<>();
-        nameToSlotMap = new HashMap<>();
+        identifierToSlotMap = new HashMap<>();
         lastVersion = new FrameVersionImpl();
     }
 
-    public FrameSlot addFrameSlot(String name) {
-        return addFrameSlot(name, typeConversion.getTopType());
+    public FrameSlot addFrameSlot(Object identifier) {
+        return addFrameSlot(identifier, typeConversion.getTopType());
     }
 
-    public FrameSlot addFrameSlot(String name, Class<?> type) {
-        assert !nameToSlotMap.containsKey(name);
-        FrameSlotImpl slot = new FrameSlotImpl(this, name, slots.size(), type);
+    public FrameSlot addFrameSlot(Object identifier, Class<?> type) {
+        assert !identifierToSlotMap.containsKey(identifier);
+        FrameSlotImpl slot = new FrameSlotImpl(this, identifier, slots.size(), type);
         slots.add(slot);
-        nameToSlotMap.put(name, slot);
+        identifierToSlotMap.put(identifier, slot);
         return slot;
     }
 
-    public FrameSlot findFrameSlot(String name) {
-        return nameToSlotMap.get(name);
+    public FrameSlot findFrameSlot(Object identifier) {
+        return identifierToSlotMap.get(identifier);
     }
 
-    public FrameSlot findOrAddFrameSlot(String name) {
-        FrameSlot result = findFrameSlot(name);
+    public FrameSlot findOrAddFrameSlot(Object identifier) {
+        FrameSlot result = findFrameSlot(identifier);
         if (result != null) {
             return result;
         }
-        return addFrameSlot(name);
+        return addFrameSlot(identifier);
     }
 
     public FrameVersion getCurrentVersion() {
@@ -120,21 +120,21 @@
 class FrameSlotImpl implements FrameSlot {
 
     private final FrameDescriptor descriptor;
-    private final String name;
+    private final Object identifier;
     private final int index;
     private Class<?> type;
     private ArrayList<FrameSlotTypeListener> listeners;
 
-    protected FrameSlotImpl(FrameDescriptor descriptor, String name, int index, Class<?> type) {
+    protected FrameSlotImpl(FrameDescriptor descriptor, Object identifier, int index, Class<?> type) {
         this.descriptor = descriptor;
-        this.name = name;
+        this.identifier = identifier;
         this.index = index;
         this.type = type;
         assert type != null;
     }
 
-    public String getName() {
-        return name;
+    public Object getIdentifier() {
+        return identifier;
     }
 
     public int getIndex() {
@@ -189,7 +189,7 @@
 
     @Override
     public String toString() {
-        return "[" + index + "," + name + "]";
+        return "[" + index + "," + identifier + "]";
     }
 
     @Override
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java	Mon Feb 11 10:41:29 2013 +0100
@@ -27,7 +27,7 @@
  */
 public interface FrameSlot {
 
-    String getName();
+    Object getIdentifier();
 
     int getIndex();
 
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java	Mon Feb 11 10:41:29 2013 +0100
@@ -126,4 +126,9 @@
     @Override
     public void updateToLatestVersion() {
     }
+
+    @Override
+    public FrameDescriptor getFrameDescriptor() {
+        throw new UnsupportedOperationException("native frame");
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/PackedFrame.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/PackedFrame.java	Mon Feb 11 10:41:29 2013 +0100
@@ -35,5 +35,5 @@
      * 
      * @return the virtual frame that was the content of this packed frame
      */
-    VirtualFrame unpack();
+    Frame unpack();
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/VirtualFrame.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/VirtualFrame.java	Mon Feb 11 10:41:29 2013 +0100
@@ -35,29 +35,10 @@
 public interface VirtualFrame extends Frame {
 
     /**
-     * Converts this virtual frame into a packed frame that has no longer direct access to the local
-     * variables. This packing is an important hint to the Truffle optimizer and therefore passing
-     * around a {@link PackedFrame} should be preferred over passing around a {@link VirtualFrame}
-     * when the probability that an unpacking will occur is low.
-     * 
-     * @return the packed frame
-     */
-    PackedFrame pack();
-
-    /**
      * Accesses the caller frame passed in via {@link CallTarget#call}. To get full access, it must
      * be first unpacked using {@link PackedFrame#unpack()}.
      * 
      * @return the caller frame or null if this was a root method call
      */
     PackedFrame getCaller();
-
-    /**
-     * Materializes this frame, which allows it to be stored in a field or cast to
-     * {@link java.lang.Object}. The frame however looses the ability to be packed or to access the
-     * caller frame.
-     * 
-     * @return the new materialized frame
-     */
-    MaterializedFrame materialize();
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java	Mon Feb 11 10:41:29 2013 +0100
@@ -25,7 +25,7 @@
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 
-final class DefaultMaterializedFrame implements MaterializedFrame {
+final class DefaultMaterializedFrame implements MaterializedFrame, PackedFrame {
 
     private final DefaultVirtualFrame wrapped;
 
@@ -102,4 +102,24 @@
     public void updateToLatestVersion() {
         wrapped.updateToLatestVersion();
     }
+
+    @Override
+    public PackedFrame pack() {
+        return this;
+    }
+
+    @Override
+    public MaterializedFrame materialize() {
+        return this;
+    }
+
+    @Override
+    public Frame unpack() {
+        return this;
+    }
+
+    @Override
+    public FrameDescriptor getFrameDescriptor() {
+        return wrapped.getFrameDescriptor();
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Mon Feb 11 10:41:29 2013 +0100
@@ -46,4 +46,14 @@
     public CallTarget createCallTarget(RootNode rootNode) {
         return createCallTarget(rootNode, new FrameDescriptor());
     }
+
+    @Override
+    public MaterializedFrame createMaterializedFrame(Arguments arguments) {
+        return createMaterializedFrame(arguments, new FrameDescriptor());
+    }
+
+    @Override
+    public MaterializedFrame createMaterializedFrame(Arguments arguments, FrameDescriptor frameDescriptor) {
+        return new DefaultMaterializedFrame(new DefaultVirtualFrame(frameDescriptor, null, arguments));
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Mon Feb 11 10:41:29 2013 +0100
@@ -192,4 +192,9 @@
         }
         currentVersion = version;
     }
+
+    @Override
+    public FrameDescriptor getFrameDescriptor() {
+        return this.descriptor;
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ControlFlowException.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ControlFlowException.java	Mon Feb 11 10:41:29 2013 +0100
@@ -39,8 +39,9 @@
     /**
      * For performance reasons, this exception does not record any stack trace information.
      */
+    @SuppressWarnings("sync-override")
     @Override
-    public synchronized Throwable fillInStackTrace() {
+    public final Throwable fillInStackTrace() {
         return null;
     }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java	Mon Feb 11 10:41:02 2013 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java	Mon Feb 11 10:41:29 2013 +0100
@@ -54,8 +54,9 @@
     /**
      * For performance reasons, this exception does not record any stack trace information.
      */
+    @SuppressWarnings("sync-override")
     @Override
-    public synchronized Throwable fillInStackTrace() {
+    public Throwable fillInStackTrace() {
         return null;
     }
 }
--- a/make/solaris/makefiles/compiler1.make	Mon Feb 11 10:41:02 2013 +0100
+++ b/make/solaris/makefiles/compiler1.make	Mon Feb 11 10:41:29 2013 +0100
@@ -29,3 +29,7 @@
 VM_SUBDIR = client
 
 CFLAGS += -DCOMPILER1
+
+ifndef OMIT_GRAAL
+  CFLAGS += -DGRAAL
+endif
--- a/make/solaris/makefiles/compiler2.make	Mon Feb 11 10:41:02 2013 +0100
+++ b/make/solaris/makefiles/compiler2.make	Mon Feb 11 10:41:29 2013 +0100
@@ -29,3 +29,7 @@
 VM_SUBDIR = server
 
 CFLAGS += -DCOMPILER2
+
+ifndef OMIT_GRAAL
+  CFLAGS += -DGRAAL
+endif
--- a/make/solaris/makefiles/debug.make	Mon Feb 11 10:41:02 2013 +0100
+++ b/make/solaris/makefiles/debug.make	Mon Feb 11 10:41:29 2013 +0100
@@ -43,7 +43,7 @@
 MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \
           $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug
 #ifdef GRAAL
-MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-graal
+MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-GRAAL
 #endif
 
 # This mapfile is only needed when compiling with dtrace support, 
--- a/make/solaris/makefiles/fastdebug.make	Mon Feb 11 10:41:02 2013 +0100
+++ b/make/solaris/makefiles/fastdebug.make	Mon Feb 11 10:41:29 2013 +0100
@@ -118,7 +118,7 @@
 MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \
 	  $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug
 #ifdef GRAAL
-MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-graal
+MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-GRAAL
 #endif
 
 # This mapfile is only needed when compiling with dtrace support, 
--- a/make/solaris/makefiles/jvmg.make	Mon Feb 11 10:41:02 2013 +0100
+++ b/make/solaris/makefiles/jvmg.make	Mon Feb 11 10:41:29 2013 +0100
@@ -47,7 +47,7 @@
 MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \
           $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug
 #ifdef GRAAL
-MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-graal
+MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-GRAAL
 #endif
 
 # This mapfile is only needed when compiling with dtrace support,
--- a/make/solaris/makefiles/optimized.make	Mon Feb 11 10:41:02 2013 +0100
+++ b/make/solaris/makefiles/optimized.make	Mon Feb 11 10:41:29 2013 +0100
@@ -55,7 +55,7 @@
 # Linker mapfiles
 MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers
 #ifdef GRAAL
-MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-graal
+MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-GRAAL
 #endif
 
 # This mapfile is only needed when compiling with dtrace support, 
--- a/make/solaris/makefiles/product.make	Mon Feb 11 10:41:02 2013 +0100
+++ b/make/solaris/makefiles/product.make	Mon Feb 11 10:41:29 2013 +0100
@@ -67,7 +67,7 @@
 # Linker mapfiles
 MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers
 ifdef GRAAL
-MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-graal
+MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-GRAAL
 endif
 
 ifndef USE_GCC
--- a/make/solaris/makefiles/tiered.make	Mon Feb 11 10:41:02 2013 +0100
+++ b/make/solaris/makefiles/tiered.make	Mon Feb 11 10:41:29 2013 +0100
@@ -29,3 +29,7 @@
 VM_SUBDIR = server
 
 CFLAGS += -DCOMPILER2 -DCOMPILER1
+
+ifndef OMIT_GRAAL
+  CFLAGS += -DGRAAL
+endif
--- a/make/solaris/makefiles/vm.make	Mon Feb 11 10:41:02 2013 +0100
+++ b/make/solaris/makefiles/vm.make	Mon Feb 11 10:41:29 2013 +0100
@@ -192,11 +192,11 @@
 
 # Include dirs per type.
 Src_Dirs/CORE      := $(CORE_PATHS)
-Src_Dirs/COMPILER1 := $(CORE_PATHS) $(COMPILER1_PATHS)
-Src_Dirs/COMPILER2 := $(CORE_PATHS) $(COMPILER2_PATHS)
-Src_Dirs/TIERED    := $(CORE_PATHS) $(COMPILER1_PATHS) $(COMPILER2_PATHS)
+Src_Dirs/COMPILER1 := $(CORE_PATHS) $(COMPILER1_PATHS) $(GRAAL_PATHS)
+Src_Dirs/COMPILER2 := $(CORE_PATHS) $(COMPILER2_PATHS) $(GRAAL_PATHS)
+Src_Dirs/TIERED    := $(CORE_PATHS) $(COMPILER1_PATHS) $(COMPILER2_PATHS) $(GRAAL_PATHS)
 Src_Dirs/ZERO      := $(CORE_PATHS)
-Src_Dirs/SHARK     := $(CORE_PATHS)
+Src_Dirs/SHARK     := $(CORE_PATHS) $(SHARK_PATHS)
 Src_Dirs/GRAAL     := $(CORE_PATHS) $(GRAAL_PATHS)
 Src_Dirs := $(Src_Dirs/$(TYPE))
 
@@ -216,7 +216,7 @@
 Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
 Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
 Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
-Src_Files_EXCLUDE/GRAAL     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/GRAAL     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
 
 Src_Files_EXCLUDE +=  $(Src_Files_EXCLUDE/$(TYPE))
 
--- a/mx/commands.py	Mon Feb 11 10:41:02 2013 +0100
+++ b/mx/commands.py	Mon Feb 11 10:41:29 2013 +0100
@@ -786,7 +786,7 @@
             tasks.append(t.stop())
         
         t = Task('BuildJava')
-        build(['--no-native'])
+        build(['--no-native', '--jdt-warning-as-error'])
         tasks.append(t.stop())
         
         if exists('jacoco.exec'):
@@ -966,7 +966,7 @@
     if ('specjbb2005' in args or 'all' in args):
         benchmarks += [sanitycheck.getSPECjbb2005()]
         
-    if ('specjbb2013' in args or 'all' in args):
+    if ('specjbb2013' in args): # or 'all' in args //currently not in default set
         benchmarks += [sanitycheck.getSPECjbb2013()]
 
     for test in benchmarks:
--- a/mx/projects	Mon Feb 11 10:41:02 2013 +0100
+++ b/mx/projects	Mon Feb 11 10:41:29 2013 +0100
@@ -55,13 +55,6 @@
 project@com.oracle.graal.api.code@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.api.code@javaCompliance=1.7
 
-# graal.api.interpreter
-project@com.oracle.graal.api.interpreter@subDir=graal
-project@com.oracle.graal.api.interpreter@sourceDirs=src
-project@com.oracle.graal.api.interpreter@dependencies=com.oracle.graal.api.meta
-project@com.oracle.graal.api.interpreter@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.api.interpreter@javaCompliance=1.7
-
 # graal.amd64
 project@com.oracle.graal.amd64@subDir=graal
 project@com.oracle.graal.amd64@sourceDirs=src
@@ -69,10 +62,17 @@
 project@com.oracle.graal.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.amd64@javaCompliance=1.7
 
+# graal.sparc
+project@com.oracle.graal.sparc@subDir=graal
+project@com.oracle.graal.sparc@sourceDirs=src
+project@com.oracle.graal.sparc@dependencies=com.oracle.graal.api.code
+project@com.oracle.graal.sparc@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.sparc@javaCompliance=1.7
+
 # graal.hotspot
 project@com.oracle.graal.hotspot@subDir=graal
 project@com.oracle.graal.hotspot@sourceDirs=src
-project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.snippets,com.oracle.graal.api.interpreter,com.oracle.graal.api.runtime,com.oracle.graal.printer
+project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.snippets,com.oracle.graal.api.runtime,com.oracle.graal.printer
 project@com.oracle.graal.hotspot@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot@javaCompliance=1.7
 
@@ -83,6 +83,13 @@
 project@com.oracle.graal.hotspot.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.amd64@javaCompliance=1.7
 
+# graal.hotspot.sparc
+project@com.oracle.graal.hotspot.sparc@subDir=graal
+project@com.oracle.graal.hotspot.sparc@sourceDirs=src
+project@com.oracle.graal.hotspot.sparc@dependencies=com.oracle.graal.hotspot,com.oracle.graal.compiler.sparc
+project@com.oracle.graal.hotspot.sparc@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.hotspot.sparc@javaCompliance=1.7
+
 # graal.hotspot.server
 project@com.oracle.graal.hotspot.server@subDir=graal
 project@com.oracle.graal.hotspot.server@sourceDirs=src
@@ -130,6 +137,13 @@
 project@com.oracle.graal.lir.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.lir.amd64@javaCompliance=1.7
 
+# graal.lir.sparc
+project@com.oracle.graal.lir.sparc@subDir=graal
+project@com.oracle.graal.lir.sparc@sourceDirs=src
+project@com.oracle.graal.lir.sparc@dependencies=com.oracle.graal.lir,com.oracle.graal.asm.sparc
+project@com.oracle.graal.lir.sparc@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.lir.sparc@javaCompliance=1.7
+
 # graal.alloc
 project@com.oracle.graal.alloc@subDir=graal
 project@com.oracle.graal.alloc@sourceDirs=src
@@ -165,13 +179,6 @@
 project@com.oracle.graal.nodes@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.nodes@javaCompliance=1.7
 
-# graal.interpreter
-project@com.oracle.graal.interpreter@subDir=graal
-project@com.oracle.graal.interpreter@sourceDirs=src
-project@com.oracle.graal.interpreter@dependencies=com.oracle.graal.api.interpreter,com.oracle.graal.bytecode,com.oracle.graal.api.runtime
-project@com.oracle.graal.interpreter@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.interpreter@javaCompliance=1.7
-
 # graal.phases
 project@com.oracle.graal.phases@subDir=graal
 project@com.oracle.graal.phases@sourceDirs=src
@@ -214,6 +221,13 @@
 project@com.oracle.graal.compiler.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.amd64@javaCompliance=1.7
 
+# graal.compiler.sparc
+project@com.oracle.graal.compiler.sparc@subDir=graal
+project@com.oracle.graal.compiler.sparc@sourceDirs=src
+project@com.oracle.graal.compiler.sparc@dependencies=com.oracle.graal.compiler,com.oracle.graal.lir.sparc
+project@com.oracle.graal.compiler.sparc@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.compiler.sparc@javaCompliance=1.7
+
 # graal.bytecode
 project@com.oracle.graal.bytecode@subDir=graal
 project@com.oracle.graal.bytecode@sourceDirs=src
@@ -234,10 +248,17 @@
 project@com.oracle.graal.printer@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.printer@javaCompliance=1.7
 
+# graal.test
+project@com.oracle.graal.test@subDir=graal
+project@com.oracle.graal.test@sourceDirs=src
+project@com.oracle.graal.test@dependencies=JUNIT
+project@com.oracle.graal.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.test@javaCompliance=1.7
+
 # graal.compiler.test
 project@com.oracle.graal.compiler.test@subDir=graal
 project@com.oracle.graal.compiler.test@sourceDirs=src
-project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.printer,JUNIT
+project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.printer,com.oracle.graal.test
 project@com.oracle.graal.compiler.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.test@javaCompliance=1.7
 
@@ -255,6 +276,13 @@
 project@com.oracle.graal.asm@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.asm@javaCompliance=1.7
 
+# graal.asm.test
+project@com.oracle.graal.asm.test@subDir=graal
+project@com.oracle.graal.asm.test@sourceDirs=src
+project@com.oracle.graal.asm.test@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.test,com.oracle.graal.asm
+project@com.oracle.graal.asm.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.asm.test@javaCompliance=1.7
+
 # graal.asm.amd64
 project@com.oracle.graal.asm.amd64@subDir=graal
 project@com.oracle.graal.asm.amd64@sourceDirs=src
@@ -262,6 +290,20 @@
 project@com.oracle.graal.asm.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.asm.amd64@javaCompliance=1.7
 
+# graal.asm.amd64.test
+project@com.oracle.graal.asm.amd64.test@subDir=graal
+project@com.oracle.graal.asm.amd64.test@sourceDirs=src
+project@com.oracle.graal.asm.amd64.test@dependencies=com.oracle.graal.asm.test,com.oracle.graal.asm.amd64
+project@com.oracle.graal.asm.amd64.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.asm.amd64.test@javaCompliance=1.7
+
+# graal.asm.sparc
+project@com.oracle.graal.asm.sparc@subDir=graal
+project@com.oracle.graal.asm.sparc@sourceDirs=src
+project@com.oracle.graal.asm.sparc@dependencies=com.oracle.graal.asm,com.oracle.graal.sparc
+project@com.oracle.graal.asm.sparc@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.asm.sparc@javaCompliance=1.7
+
 # truffle.api
 project@com.oracle.truffle.api@subDir=graal
 project@com.oracle.truffle.api@sourceDirs=src
--- a/src/cpu/sparc/vm/c2_globals_sparc.hpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/cpu/sparc/vm/c2_globals_sparc.hpp	Mon Feb 11 10:41:29 2013 +0100
@@ -37,6 +37,7 @@
 define_pd_global(bool, PreferInterpreterNativeStubs, false);
 define_pd_global(bool, ProfileTraps,                 true);
 define_pd_global(bool, UseOnStackReplacement,        true);
+define_pd_global(intx, TypeProfileWidth,             2   );
 #ifdef CC_INTERP
 define_pd_global(bool, ProfileInterpreter,           false);
 #else
--- a/src/cpu/sparc/vm/frame_sparc.inline.hpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/cpu/sparc/vm/frame_sparc.inline.hpp	Mon Feb 11 10:41:29 2013 +0100
@@ -74,7 +74,8 @@
 
 // return address:
 
-inline address  frame::sender_pc()        const    { return *I7_addr() + pc_return_offset; }
+inline address* frame::sender_pc_addr()   const { return (address*) (I7_addr() + pc_return_offset); }
+inline address  frame::sender_pc()        const { return *sender_pc_addr(); }
 
 inline address* frame::I7_addr() const  { return (address*) &sp()[ I7->sp_offset_in_saved_window()]; }
 inline address* frame::I0_addr() const  { return (address*) &sp()[ I0->sp_offset_in_saved_window()]; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/sparc/vm/graalGlobals_sparc.hpp	Mon Feb 11 10:41:29 2013 +0100
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2000, 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.
+ *
+ */
+
+#ifndef CPU_SPARC_VM_GRAALGLOBALS_SPARC_HPP
+#define CPU_SPARC_VM_GRAALGLOBALS_SPARC_HPP
+
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
+
+// Sets the default values for platform dependent flags used by the Graal compiler.
+// (see graalGlobals.hpp)
+
+define_pd_global(intx, GraalSafepointPollOffset,     0    );
+
+#endif // CPU_SPARC_VM_GRAALGLOBALS_SPARC_HPP
--- a/src/cpu/sparc/vm/jniTypes_sparc.hpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/cpu/sparc/vm/jniTypes_sparc.hpp	Mon Feb 11 10:41:29 2013 +0100
@@ -112,6 +112,25 @@
                                                           return *(jdouble *)&jl; }
 #endif
 
+  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) {
+    jlong result = get_long(from + pos);
+    pos += 2;
+    return result;
+  }
+  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) {
+    jdouble result = get_double(from + pos);
+    pos += 2;
+    return result;
+  }
 };
 
 #endif // CPU_SPARC_VM_JNITYPES_SPARC_HPP
--- a/src/cpu/x86/vm/frame_x86.hpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/cpu/x86/vm/frame_x86.hpp	Mon Feb 11 10:41:29 2013 +0100
@@ -191,8 +191,6 @@
   // Note: not necessarily the real 'frame pointer' (see real_fp)
   intptr_t*   fp() const { return _fp; }
 
-  inline address* sender_pc_addr() const;
-
   // return address of param, zero origin index.
   inline address* native_param_addr(int idx) const;
 
--- a/src/os/windows/vm/os_windows.cpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/os/windows/vm/os_windows.cpp	Mon Feb 11 10:41:29 2013 +0100
@@ -2103,18 +2103,32 @@
 #ifdef _M_IA64
   assert(0, "Fix Handle_IDiv_Exception");
 #elif _M_AMD64
-  PCONTEXT ctx = exceptionInfo->ContextRecord;
-  address pc = (address)ctx->Rip;
-#ifndef GRAAL
-  assert(pc[0] == 0xF7, "not an idiv opcode");
-  assert((pc[1] & ~0x7) == 0xF8, "cannot handle non-register operands");
-  assert(ctx->Rax == min_jint, "unexpected idiv exception");
-#endif
-  // set correct result values and continue after idiv instruction
-  ctx->Rip = (DWORD)pc + 2;        // idiv reg, reg  is 2 bytes
-  ctx->Rax = (DWORD)min_jint;      // result
-  ctx->Rdx = (DWORD)0;             // remainder
-  // Continue the execution
+  #ifdef GRAAL
+    PCONTEXT ctx = exceptionInfo->ContextRecord;
+    address pc = (address)ctx->Rip;
+    assert(pc[0] == 0x48 && pc[1] == 0xF7 || pc[0] == 0xF7, "not an idiv opcode");
+    if (pc[0] == 0x48) {
+      // set correct result values and continue after idiv instruction
+      ctx->Rip = (DWORD64)pc + 3;        // REX idiv reg, reg  is 3 bytes
+      ctx->Rax = (DWORD64)min_jlong;     // result
+    } else {
+      ctx->Rip = (DWORD64)pc + 2;        // idiv reg, reg  is 2 bytes
+      ctx->Rax = (DWORD64)min_jint;      // result
+    }
+    ctx->Rdx = (DWORD64)0;             // remainder
+    // Continue the execution
+  #else
+    PCONTEXT ctx = exceptionInfo->ContextRecord;
+    address pc = (address)ctx->Rip;
+    assert(pc[0] == 0xF7, "not an idiv opcode");
+    assert((pc[1] & ~0x7) == 0xF8, "cannot handle non-register operands");
+    assert(ctx->Rax == min_jint, "unexpected idiv exception");
+    // set correct result values and continue after idiv instruction
+    ctx->Rip = (DWORD)pc + 2;        // idiv reg, reg  is 2 bytes
+    ctx->Rax = (DWORD)min_jint;      // result
+    ctx->Rdx = (DWORD)0;             // remainder
+    // Continue the execution
+  #endif // GRAAL
 #else
   PCONTEXT ctx = exceptionInfo->ContextRecord;
   address pc = (address)ctx->Eip;
--- a/src/share/vm/classfile/vmSymbols.hpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/classfile/vmSymbols.hpp	Mon Feb 11 10:41:29 2013 +0100
@@ -339,7 +339,6 @@
   template(compileMethod_name,                    "compileMethod")                                                                    \
   template(compileMethod_signature,               "(JLcom/oracle/graal/hotspot/meta/HotSpotResolvedObjectType;IZI)Z")                 \
   template(setOption_name,                        "setOption")                                                                        \
-  template(setDefaultOptions_name,                "setDefaultOptions")                                                                \
   template(setOption_signature,                   "(Ljava/lang/String;)Z")                                                            \
   template(createUnresolvedJavaMethod_name,       "createUnresolvedJavaMethod")                                                       \
   template(createUnresolvedJavaMethod_signature,  "(Ljava/lang/String;Ljava/lang/String;Lcom/oracle/graal/api/meta/JavaType;)Lcom/oracle/graal/api/meta/JavaMethod;") \
--- a/src/share/vm/code/dependencies.cpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/code/dependencies.cpp	Mon Feb 11 10:41:29 2013 +0100
@@ -30,6 +30,7 @@
 #include "code/dependencies.hpp"
 #include "compiler/compileLog.hpp"
 #include "oops/oop.inline.hpp"
+#include "oops/objArrayKlass.hpp"
 #include "runtime/handles.hpp"
 #include "runtime/handles.inline.hpp"
 #include "utilities/copy.hpp"
--- a/src/share/vm/code/nmethod.cpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/code/nmethod.cpp	Mon Feb 11 10:41:29 2013 +0100
@@ -595,7 +595,7 @@
 {
   assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR");
   code_buffer->finalize_oop_references(method);
-  size_t leaf_graph_ids_size = leaf_graph_ids == NULL ? 0 : round_to(sizeof(jlong) * leaf_graph_ids->length(), oopSize);
+  int leaf_graph_ids_size = leaf_graph_ids == NULL ? 0 : round_to(sizeof(jlong) * leaf_graph_ids->length(), oopSize);
   // create nmethod
   nmethod* nm = NULL;
   { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
@@ -911,7 +911,7 @@
       _unwind_handler_offset = -1;
     }
 
-    size_t leaf_graph_ids_size = leaf_graph_ids == NULL ? 0 : round_to(sizeof(jlong) * leaf_graph_ids->length(), oopSize);
+    int leaf_graph_ids_size = leaf_graph_ids == NULL ? 0 : round_to(sizeof(jlong) * leaf_graph_ids->length(), oopSize);
 
     _oops_offset             = data_offset();
     _metadata_offset         = _oops_offset          + round_to(code_buffer->total_oop_size(), oopSize);
--- a/src/share/vm/code/stubs.cpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/code/stubs.cpp	Mon Feb 11 10:41:29 2013 +0100
@@ -254,7 +254,7 @@
   guarantee(_queue_begin != _queue_end || n == 0, "buffer indices must be the same");
 }
 
-void StubQueue::print_on(outputStream* st) {
+void StubQueue::print_on(outputStream* st) const {
   MutexLockerEx lock(_mutex);
   for (Stub* s = first(); s != NULL; s = next(s)) {
     stub_print(s, st);
--- a/src/share/vm/code/stubs.hpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/code/stubs.hpp	Mon Feb 11 10:41:29 2013 +0100
@@ -107,20 +107,21 @@
  public:
   // Initialization/finalization
   virtual void    initialize(Stub* self, int size,
-                             CodeComments& comments)       = 0; // called after creation (called twice if allocated via (request, commit))
-  virtual void    finalize(Stub* self)                     = 0; // called before deallocation
+                             CodeComments& comments)           = 0; // called after creation (called twice if allocated via (request, commit))
+  virtual void    finalize(Stub* self)                         = 0; // called before deallocation
 
   // General info/converters
-  virtual int     size(Stub* self) const                   = 0; // the total size of the stub in bytes (must be a multiple of CodeEntryAlignment)
-  virtual int     code_size_to_size(int code_size) const   = 0; // computes the total stub size in bytes given the code size in bytes
+  virtual int     size(Stub* self) const                       = 0; // the total size of the stub in bytes (must be a multiple of CodeEntryAlignment)
+  virtual int     code_size_to_size(int code_size) const       = 0; // computes the total stub size in bytes given the code size in bytes
 
   // Code info
-  virtual address code_begin(Stub* self) const             = 0; // points to the first code byte
-  virtual address code_end(Stub* self) const               = 0; // points to the first byte after the code
+  virtual address code_begin(Stub* self) const                 = 0; // points to the first code byte
+  virtual address code_end(Stub* self) const                   = 0; // points to the first byte after the code
 
   // Debugging
-  virtual void    verify(Stub* self)                       = 0; // verifies the stub
-  virtual void    print_on(Stub* self, outputStream* st)   = 0; // prints information about the stub
+  virtual void    verify(Stub* self) const                     = 0; // verifies the stub
+  NOT_PRODUCT(using AllocatedObj::print_on;)
+  virtual void    print_on(Stub* self, outputStream* st) const = 0; // prints information about the stub
 };
 
 
@@ -128,28 +129,29 @@
 // class, forwarding stub interface calls to the corresponding
 // stub calls.
 
-#define DEF_STUB_INTERFACE(stub)                           \
-  class stub##Interface: public StubInterface {            \
-   private:                                                \
-    static stub*    cast(Stub* self)                       { return (stub*)self; }                 \
-                                                           \
-   public:                                                 \
-    /* Initialization/finalization */                      \
-    virtual void    initialize(Stub* self, int size,       \
-                               CodeComments& comments)     { cast(self)->initialize(size, comments); } \
-    virtual void    finalize(Stub* self)                   { cast(self)->finalize(); }             \
-                                                           \
-    /* General info */                                     \
-    virtual int     size(Stub* self) const                 { return cast(self)->size(); }          \
-    virtual int     code_size_to_size(int code_size) const { return stub::code_size_to_size(code_size); } \
-                                                           \
-    /* Code info */                                        \
-    virtual address code_begin(Stub* self) const           { return cast(self)->code_begin(); }    \
-    virtual address code_end(Stub* self) const             { return cast(self)->code_end(); }      \
-                                                           \
-    /* Debugging */                                        \
-    virtual void    verify(Stub* self)                     { cast(self)->verify(); }               \
-    virtual void    print_on(Stub* self, outputStream* st) { cast(self)->print_on(st); }           \
+#define DEF_STUB_INTERFACE(stub)                                 \
+  class stub##Interface: public StubInterface {                  \
+   private:                                                      \
+    static stub*    cast(Stub* self)                             { return (stub*)self; }                 \
+                                                                 \
+   public:                                                       \
+    /* Initialization/finalization */                            \
+    virtual void    initialize(Stub* self, int size,             \
+                               CodeComments& comments)           { cast(self)->initialize(size, comments); } \
+    virtual void    finalize(Stub* self)                         { cast(self)->finalize(); }             \
+                                                                 \
+    /* General info */                                           \
+    virtual int     size(Stub* self) const                       { return cast(self)->size(); }          \
+    virtual int     code_size_to_size(int code_size) const       { return stub::code_size_to_size(code_size); } \
+                                                                 \
+    /* Code info */                                              \
+    virtual address code_begin(Stub* self) const                 { return cast(self)->code_begin(); }    \
+    virtual address code_end(Stub* self) const                   { return cast(self)->code_end(); }      \
+                                                                 \
+    /* Debugging */                                              \
+    virtual void    verify(Stub* self) const                     { cast(self)->verify(); }               \
+    NOT_PRODUCT(using AllocatedObj::print_on;)                   \
+    virtual void    print_on(Stub* self, outputStream* st) const { cast(self)->print_on(st); }           \
   };
 
 
@@ -182,7 +184,7 @@
   bool  stub_contains(Stub* s, address pc) const { return _stub_interface->code_begin(s) <= pc && pc < _stub_interface->code_end(s); }
   int   stub_code_size_to_size(int code_size) const { return _stub_interface->code_size_to_size(code_size); }
   void  stub_verify(Stub* s)                     { _stub_interface->verify(s); }
-  void  stub_print(Stub* s, outputStream* st)    { _stub_interface->print_on(s, st); }
+  void  stub_print(Stub* s, outputStream* st) const { _stub_interface->print_on(s, st); }
 
   static void register_queue(StubQueue*);
 
@@ -226,9 +228,9 @@
   address stub_code_end(Stub* s) const           { return _stub_interface->code_end(s);   }
 
   // Debugging/printing
-  void  verify();                                // verifies the stub queue
-  void  print()                                  { print_on(tty); }
-  void  print_on(outputStream* st);
+  void verify();                                 // verifies the stub queue
+  virtual void print() const                     { print_on(tty); }
+  virtual void print_on(outputStream* st) const;
 };
 
 #endif // SHARE_VM_CODE_STUBS_HPP
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Mon Feb 11 10:41:29 2013 +0100
@@ -22,6 +22,7 @@
  */
 
 #include "precompiled.hpp"
+#include "compiler/disassembler.hpp"
 #include "runtime/javaCalls.hpp"
 #include "graal/graalEnv.hpp"
 #include "graal/graalCompiler.hpp"
@@ -30,27 +31,38 @@
 #include "graal/graalCompilerToVM.hpp"
 #include "graal/graalVmIds.hpp"
 #include "graal/graalRuntime.hpp"
+#include "asm/register.hpp"
 #include "classfile/vmSymbols.hpp"
-#include "vmreg_x86.inline.hpp"
-
+#include "code/vmreg.hpp"
 
-// TODO this should be handled in a more robust way - not hard coded...
-Register CPU_REGS[] = { rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15 };
-bool OOP_ALLOWED[] = {true, true, true, true, false, false, true, true, true, true, false, true, true, true, true, true};
-const static int NUM_CPU_REGS = sizeof(CPU_REGS) / sizeof(Register);
-XMMRegister XMM_REGS[] = { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 };
-const static int NUM_XMM_REGS = sizeof(XMM_REGS) / sizeof(XMMRegister);
-const static int NUM_REGS = NUM_CPU_REGS + NUM_XMM_REGS;
-const static jlong NO_REF_MAP = 0x8000000000000000L;
+#ifdef TARGET_ARCH_x86
+# include "vmreg_x86.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_sparc
+# include "vmreg_sparc.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_zero
+# include "vmreg_zero.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_arm
+# include "vmreg_arm.inline.hpp"
+#endif
+#ifdef TARGET_ARCH_ppc
+# include "vmreg_ppc.inline.hpp"
+#endif
 
 // convert Graal register indices (as used in oop maps) to HotSpot registers
 VMReg get_hotspot_reg(jint graal_reg) {
-
-  assert(graal_reg >= 0 && graal_reg < NUM_REGS, "invalid register number");
-  if (graal_reg < NUM_CPU_REGS) {
-    return CPU_REGS[graal_reg]->as_VMReg();
+  if (graal_reg < RegisterImpl::number_of_registers) {
+    return as_Register(graal_reg)->as_VMReg();
   } else {
-    return XMM_REGS[graal_reg - NUM_CPU_REGS]->as_VMReg();
+    int remainder = graal_reg - RegisterImpl::number_of_registers;
+#ifdef TARGET_ARCH_x86
+    if (remainder < XMMRegisterImpl::number_of_registers) {
+      return as_XMMRegister(remainder)->as_VMReg();
+    }
+#endif
+    ShouldNotReachHere();
   }
 }
 
@@ -76,11 +88,10 @@
   oop frame_map = (oop) DebugInfo::frameRefMap(debug_info);
 
   if (register_map != NULL) {
-    for (jint i = 0; i < NUM_CPU_REGS; i++) {
+    for (jint i = 0; i < RegisterImpl::number_of_registers; i++) {
       bool is_oop = is_bit_set(register_map, i);
       VMReg reg = get_hotspot_reg(i);
       if (is_oop) {
-        assert(OOP_ALLOWED[i], "this register may never be an oop, register map misaligned?");
         map->set_oop(reg);
       } else {
         map->set_value(reg);
@@ -156,11 +167,15 @@
       } else {
         locationType = Location::dbl;
       }
+#ifdef TARGET_ARCH_x86
       ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_XMMRegister(number - 16)->as_VMReg()));
       if (type == T_DOUBLE) {
         second = value;
       }
       return value;
+#else
+      ShouldNotReachHere("Platform currently does not support floating point values.");
+#endif
     }
   } else if (value->is_a(StackSlot::klass())) {
     if (type == T_DOUBLE) {
@@ -291,8 +306,15 @@
 GrowableArray<jlong>* get_leaf_graph_ids(Handle& comp_result) {
   arrayOop leafGraphArray = (arrayOop) CompilationResult::leafGraphIds(HotSpotCompilationResult::comp(comp_result));
 
-  GrowableArray<jlong>* result = new GrowableArray<jlong>(leafGraphArray->length());
-  for (int i = 0; i < leafGraphArray->length(); i++) {
+  jint length;
+  if (leafGraphArray == NULL) {
+    length = 0;
+  } else {
+    length = leafGraphArray->length();
+  }
+
+  GrowableArray<jlong>* result = new GrowableArray<jlong>(length);
+  for (int i = 0; i < length; i++) {
     result->append(((jlong*) leafGraphArray->base(T_LONG))[i]);
   }
 
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Mon Feb 11 10:41:29 2013 +0100
@@ -48,7 +48,7 @@
     MARK_POLL_NEAR                  = 0x3001,
     MARK_POLL_RETURN_NEAR           = 0x3002,
     MARK_POLL_FAR                   = 0x3003,
-    MARK_POLL_RETURN_FAR            = 0x3004,
+    MARK_POLL_RETURN_FAR            = 0x3004
   };
 
   Arena         _arena;
--- a/src/share/vm/graal/graalCompiler.cpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/graal/graalCompiler.cpp	Mon Feb 11 10:41:29 2013 +0100
@@ -79,7 +79,6 @@
   {
     GRAAL_VM_ENTRY_MARK;
     HandleMark hm;
-    VMToCompiler::setDefaultOptions();
     for (int i = 0; i < Arguments::num_graal_args(); ++i) {
       const char* arg = Arguments::graal_args_array()[i];
       Handle option = java_lang_String::create_from_str(arg, THREAD);
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Mon Feb 11 10:41:29 2013 +0100
@@ -30,6 +30,7 @@
 #include "graal/graalRuntime.hpp"
 #include "compiler/compileBroker.hpp"
 #include "compiler/compilerOracle.hpp"
+#include "compiler/disassembler.hpp"
 #include "graal/graalCompilerToVM.hpp"
 #include "graal/graalCompiler.hpp"
 #include "graal/graalEnv.hpp"
--- a/src/share/vm/graal/graalRuntime.cpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/graal/graalRuntime.cpp	Mon Feb 11 10:41:29 2013 +0100
@@ -22,12 +22,13 @@
  */
 
 #include "precompiled.hpp"
-#include "runtime/interfaceSupport.hpp"
-#include "prims/jvm.h"
+#include "asm/codeBuffer.hpp"
 #include "graal/graalRuntime.hpp"
 #include "graal/graalVMToCompiler.hpp"
-#include "asm/codeBuffer.hpp"
+#include "memory/oopFactory.hpp"
+#include "prims/jvm.h"
 #include "runtime/biasedLocking.hpp"
+#include "runtime/interfaceSupport.hpp"
 
 // Implementation of GraalStubAssembler
 
@@ -128,7 +129,7 @@
     // These stubs don't need to have an oopmap
     case graal_slow_subtype_check_id:
 #if defined(SPARC) || defined(PPC)
-    case handle_exception_nofpu_id:  // Unused on sparc
+    case graal_handle_exception_nofpu_id:  // Unused on sparc
 #endif
     case graal_verify_oop_id:
     case graal_unwind_exception_call_id:
--- a/src/share/vm/graal/graalVMToCompiler.cpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/graal/graalVMToCompiler.cpp	Mon Feb 11 10:41:29 2013 +0100
@@ -86,15 +86,6 @@
   return result.get_jboolean();
 }
 
-void VMToCompiler::setDefaultOptions() {
-  KlassHandle compilerKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions());
-
-  Thread* THREAD = Thread::current();
-  JavaValue result(T_VOID);
-  JavaCalls::call_static(&result, compilerKlass, vmSymbols::setDefaultOptions_name(), vmSymbols::void_method_signature(), THREAD);
-  check_pending_exception("Error while calling setDefaultOptions");
-}
-
 jboolean VMToCompiler::compileMethod(Method* method, Handle holder, int entry_bci, jboolean blocking, int priority) {
   assert(method != NULL, "just checking");
   assert(!holder.is_null(), "just checking");
--- a/src/share/vm/graal/graalVMToCompiler.hpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/graal/graalVMToCompiler.hpp	Mon Feb 11 10:41:29 2013 +0100
@@ -53,9 +53,6 @@
   // public static boolean HotSpotOptions.setOption(String option);
   static jboolean setOption(Handle option);
 
-  // public static void HotSpotOptions.setDefaultOptions();
-  static void setDefaultOptions();
-
   // public abstract boolean compileMethod(long vmId, String name, int entry_bci, boolean blocking);
   static jboolean compileMethod(Method* method, Handle holder, int entry_bci, jboolean blocking, int priority);
 
--- a/src/share/vm/runtime/arguments.cpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/runtime/arguments.cpp	Mon Feb 11 10:41:29 2013 +0100
@@ -2270,7 +2270,6 @@
           "com.oracle.graal.api.runtime",
           "com.oracle.graal.api.meta",
           "com.oracle.graal.api.code",
-          "com.oracle.graal.api.interpreter",
           "com.oracle.graal.hotspot",
           "com.oracle.graal.asm",
           "com.oracle.graal.alloc",
--- a/src/share/vm/runtime/compilationPolicy.cpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/runtime/compilationPolicy.cpp	Mon Feb 11 10:41:29 2013 +0100
@@ -492,7 +492,7 @@
   int hot_count = m->backedge_count();
   const char* comment = "backedge_count";
 
-  if (is_compilation_enabled() && !m->is_not_osr_compilable() && can_be_compiled(m)) {
+  if (is_compilation_enabled() && !m->is_not_osr_compilable() && can_be_compiled(m) && !m->queued_for_compilation() && m->code() == NULL) {
     if (TraceCompilationPolicy) {
       tty->print("backedge invocation trigger: ");
       m->print_short_name(tty);
--- a/src/share/vm/runtime/fieldDescriptor.hpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/runtime/fieldDescriptor.hpp	Mon Feb 11 10:41:29 2013 +0100
@@ -25,7 +25,10 @@
 #ifndef SHARE_VM_RUNTIME_FIELDDESCRIPTOR_HPP
 #define SHARE_VM_RUNTIME_FIELDDESCRIPTOR_HPP
 
+#include "oops/annotations.hpp"
 #include "oops/constantPool.hpp"
+#include "oops/fieldInfo.hpp"
+#include "oops/instanceKlass.hpp"
 #include "oops/symbol.hpp"
 #include "runtime/fieldType.hpp"
 #include "utilities/accessFlags.hpp"
--- a/src/share/vm/runtime/frame.cpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/runtime/frame.cpp	Mon Feb 11 10:41:29 2013 +0100
@@ -637,8 +637,10 @@
   st->print("; ");
   interpreter_frame_method()->print_name(st);
   st->cr();
+#ifdef AMD64
   // last sp
   st->print_cr(" - last sp       at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_last_sp_addr(), *interpreter_frame_last_sp_addr());
+#endif
   // sender sp
   st->print_cr(" - sender sp     at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_sender_sp_addr(), *interpreter_frame_sender_sp_addr());
   // old fp
--- a/src/share/vm/runtime/frame.hpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/runtime/frame.hpp	Mon Feb 11 10:41:29 2013 +0100
@@ -208,6 +208,7 @@
   void set_link(intptr_t* addr);
 
   // Return address
+  address* sender_pc_addr() const;
   address  sender_pc() const;
 
   // Support for deoptimization
--- a/src/share/vm/runtime/java.cpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/runtime/java.cpp	Mon Feb 11 10:41:29 2013 +0100
@@ -375,6 +375,10 @@
     CompileBroker::print_times();
   }
 
+  if(PrintNMethodStatistics) {
+    nmethod::print_statistics();
+  }
+
   if (PrintCodeCache) {
     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     CodeCache::print();
--- a/src/share/vm/utilities/machineCodePrinter.cpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/utilities/machineCodePrinter.cpp	Mon Feb 11 10:41:29 2013 +0100
@@ -21,7 +21,10 @@
  * questions.
  */
 
-#include "precompiled.hpp"
+#include "precompiled.hpp"
+#include "code/stubs.hpp"
+#include "compiler/disassembler.hpp"
+#include "runtime/thread.hpp"
 #include "utilities/machineCodePrinter.hpp"
 #include "utilities/ostream.hpp"
 
--- a/src/share/vm/utilities/machineCodePrinter.hpp	Mon Feb 11 10:41:02 2013 +0100
+++ b/src/share/vm/utilities/machineCodePrinter.hpp	Mon Feb 11 10:41:29 2013 +0100
@@ -23,6 +23,9 @@
 
 #ifndef SHARE_VM_UTILITIES_MACHINE_CODE_PRINTER_HPP
 #define SHARE_VM_UTILITIES_MACHINE_CODE_PRINTER_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/ostream.hpp"
 
 class MachineCodePrinter : public AllStatic {
 private: