changeset 11595:003be97acdda

Merge
author Mick Jordan <mick.jordan@oracle.com>
date Tue, 10 Sep 2013 16:33:28 -0700
parents c47153857827 (diff) 3d358ea11300 (current diff)
children 91e5f927af63
files
diffstat 284 files changed, 6372 insertions(+), 2710 deletions(-) [+]
line wrap: on
line diff
--- a/README_GRAAL.txt	Tue Sep 10 16:32:27 2013 -0700
+++ b/README_GRAAL.txt	Tue Sep 10 16:33:28 2013 -0700
@@ -11,11 +11,30 @@
 
 % mx build
 
-This builds the 'product' version of HotSpot with the Graal modifications.
-To build the debug or fastdebug versions:
+There are a number of VM configurations supported by mx which can
+be explicitly specified using the --vm option. However, you'll typically
+want one of these VM configurations:
 
-  mx build debug
-  mx build fastdebug
+1. The 'server' configuration is a standard HotSpot VM that includes the
+   runtime support for Graal but uses the existing compilers for normal
+   compilation (e.g., when the interpreter threshold is hit for a method).
+   Compilation with Graal is only done by explicit requests to the
+   Graal API. This is how Truffle uses Graal.
+   
+2. The 'graal' configuration is a VM where all compilation is performed
+   by Graal and no other compilers are built into the VM binary. This
+   VM will bootstrap Graal itself at startup unless the -XX:-BootstrapGraal
+   VM option is given.   
+
+Unless you use the --vm option with the build command, you will be presented
+with a dialogue to choose one of the above VM configurations for the build
+as well as have the option to make it your default for subsequent commands
+that need a VM specified.
+
+To build the debug or fastdebug builds:
+
+% mx --vmbuild debug build
+% mx --vmbuild fastdebug build
 
 Running Graal
 -------------
@@ -24,47 +43,28 @@
 
 % mx vm ...
 
-To select the fastdebug or debug versions of the VM:
-
-% mx --fastdebug vm ...
-% mx --debug vm ...
+To select the fastdebug or debug builds of the VM:
 
-Graal has an optional bootstrap step where it compiles itself before
-compiling any application code. This bootstrap step currently takes about 7 seconds
-on a fast x64 machine. It's useful to disable this bootstrap step when running small
-programs with the -XX:-BootstrapGraal options. For example:
+% mx --vmbuild fastdebug vm ...
+% mx --vmbuild debug vm ...
 
-% mx vm -XX:-BootstrapGraal ...
-
+Other VM Configurations
+-----------------------
 
-Other Build Configurations
---------------------------
-
-By default the build commands above create a HotSpot binary where Graal
-is the only compiler. This binary is the Graal VM binary and identifies as
-such with the -version option:
+In addition to the VM configurations described above, there are
+VM configurations that omit all VM support for Graal:
 
-% mx vm -XX:-BootstrapGraal -version
-java version "1.7.0_07"
-Java(TM) SE Runtime Environment (build 1.7.0_07-b10)
-OpenJDK 64-Bit Graal VM (build 25.0-b10-internal, mixed mode)
-
-It's also possible to build and execute the standard HotSpot binaries
-using the --vm option:
+% mx --vm server-nograal build
+% mx --vm server-nograal vm -version
+java version "1.7.0_25"
+Java(TM) SE Runtime Environment (build 1.7.0_25-b15)
+OpenJDK 64-Bit Server VM (build 25.0-b43-internal, mixed mode)
 
-% mx --vm server build
-% mx --vm server vm -version
-java version "1.7.0_07"
-Java(TM) SE Runtime Environment (build 1.7.0_07-b10)
-OpenJDK 64-Bit Server VM (build 25.0-b10-internal, mixed mode)
+% mx --vm client-nograal build
+% mx --vm client-nograal vm -version
+java version "1.7.0_25"
+Java(TM) SE Runtime Environment (build 1.7.0_25-b15)
+OpenJDK 64-Bit Cleint VM (build 25.0-b43-internal, mixed mode)
 
-These standard binaries still include the code necessary to support use of the
-Graal compiler for explicit compilation requests. However, in this configuration
-the Graal compiler will not service VM issued compilation requests (e.g., upon
-counter overflow in the interpreter).
-
-To build a HotSpot binary that completely omits all VM support for Graal,
-define an environment variable OMIT_GRAAL (its value does not matter) and build
-with the --vm option as above (doing a clean first if necessary):
-
-% env OMIT_GRAAL= mx --vm server build
+These configurations aim to match as closely as possible the
+VM(s) included in the OpenJDK binaries one can download.
\ No newline at end of file
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java	Tue Sep 10 16:33:28 2013 -0700
@@ -192,7 +192,7 @@
      *            null if no arithmetic needs to be performed on the vector
      * @return a supported vector size, but at most {@code maxLength}
      */
-    public int getSupportedVectorLength(Kind kind, int maxLength, ArithmeticOperation arithmetic) {
+    public int getSupportedVectorLength(Kind kind, int maxLength, Class<? extends ArithmeticOperation> arithmetic) {
         return 1;
     }
 
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Tue Sep 10 16:33:28 2013 -0700
@@ -89,12 +89,4 @@
      * Gets a description of the target architecture.
      */
     TargetDescription getTarget();
-
-    /**
-     * Returns the register the runtime uses for maintaining the heap base address. This is mainly
-     * utilized by runtimes which support compressed pointers.
-     * 
-     * @return the register that keeps the heap base address
-     */
-    Register heapBaseRegister();
 }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Tue Sep 10 16:33:28 2013 -0700
@@ -594,6 +594,7 @@
         "getDeclaredMethods",
         "getDeclaredConstructors",
         "isInitialized",
+        "isLinked",
         "getEncoding",
         "hasFinalizableSubclass",
         "hasFinalizer",
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Tue Sep 10 16:33:28 2013 -0700
@@ -454,4 +454,102 @@
                 throw new IllegalArgumentException(kind.toString());
         }
     }
+
+    /**
+     * Returns the zero value for a given numeric kind.
+     */
+    public static Constant zero(Kind kind) {
+        switch (kind) {
+            case Byte:
+                return forByte((byte) 0);
+            case Char:
+                return forChar((char) 0);
+            case Double:
+                return DOUBLE_0;
+            case Float:
+                return FLOAT_0;
+            case Int:
+                return INT_0;
+            case Long:
+                return LONG_0;
+            case Short:
+                return forShort((short) 0);
+            default:
+                throw new IllegalArgumentException(kind.toString());
+        }
+    }
+
+    /**
+     * Returns the one value for a given numeric kind.
+     */
+    public static Constant one(Kind kind) {
+        switch (kind) {
+            case Byte:
+                return forByte((byte) 1);
+            case Char:
+                return forChar((char) 1);
+            case Double:
+                return DOUBLE_1;
+            case Float:
+                return FLOAT_1;
+            case Int:
+                return INT_1;
+            case Long:
+                return LONG_1;
+            case Short:
+                return forShort((short) 1);
+            default:
+                throw new IllegalArgumentException(kind.toString());
+        }
+    }
+
+    /**
+     * Adds two numeric constants.
+     */
+    public static Constant add(Constant x, Constant y) {
+        assert x.getKind() == y.getKind();
+        switch (x.getKind()) {
+            case Byte:
+                return forByte((byte) (x.asInt() + y.asInt()));
+            case Char:
+                return forChar((char) (x.asInt() + y.asInt()));
+            case Double:
+                return forDouble(x.asDouble() + y.asDouble());
+            case Float:
+                return forFloat(x.asFloat() + y.asFloat());
+            case Int:
+                return forInt(x.asInt() + y.asInt());
+            case Long:
+                return forLong(x.asLong() + y.asLong());
+            case Short:
+                return forShort((short) (x.asInt() + y.asInt()));
+            default:
+                throw new IllegalArgumentException(x.getKind().toString());
+        }
+    }
+
+    /**
+     * Multiplies two numeric constants.
+     */
+    public static Constant mul(Constant x, Constant y) {
+        assert x.getKind() == y.getKind();
+        switch (x.getKind()) {
+            case Byte:
+                return forByte((byte) (x.asInt() * y.asInt()));
+            case Char:
+                return forChar((char) (x.asInt() * y.asInt()));
+            case Double:
+                return forDouble(x.asDouble() * y.asDouble());
+            case Float:
+                return forFloat(x.asFloat() * y.asFloat());
+            case Int:
+                return forInt(x.asInt() * y.asInt());
+            case Long:
+                return forLong(x.asLong() * y.asLong());
+            case Short:
+                return forShort((short) (x.asInt() * y.asInt()));
+            default:
+                throw new IllegalArgumentException(x.getKind().toString());
+        }
+    }
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Tue Sep 10 16:33:28 2013 -0700
@@ -34,9 +34,14 @@
 
     /**
      * Returns the bytecode of this method, if the method has code. The returned byte array does not
-     * contain breakpoints or non-Java bytecodes.
+     * contain breakpoints or non-Java bytecodes. This may return null if the
+     * {@link #getDeclaringClass() holder} is not {@link ResolvedJavaType#isLinked() linked}.
      * 
-     * @return the bytecode of the method, or {@code null} if {@code getCodeSize() == 0}
+     * The contained constant pool indices may not be the ones found in the original class file but
+     * they can be used with the Graal API (e.g. methods in {@link ConstantPool}).
+     * 
+     * @return the bytecode of the method, or {@code null} if {@code getCodeSize() == 0} or if the
+     *         code is not ready.
      */
     byte[] getCode();
 
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Tue Sep 10 16:33:28 2013 -0700
@@ -112,7 +112,8 @@
     int getModifiers();
 
     /**
-     * Checks whether this type is initialized.
+     * Checks whether this type is initialized. If a type is initialized it implies that it was
+     * {@link #isLinked() linked} and that the static initializer has run.
      * 
      * @return {@code true} if this type is initialized
      */
@@ -124,6 +125,14 @@
     void initialize();
 
     /**
+     * Checks whether this type is linked and verified. When a type is linked the static initializer
+     * has not necessarily run. An {@link #isInitialized() initialized} type is always linked.
+     * 
+     * @return {@code true} if this type is linked
+     */
+    boolean isLinked();
+
+    /**
      * Determines if this type is either the same as, or is a superclass or superinterface of, the
      * type represented by the specified parameter. This method is identical to
      * {@link Class#isAssignableFrom(Class)} in terms of the value return for this type.
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Tue Sep 10 16:33:28 2013 -0700
@@ -272,59 +272,69 @@
     }
 
     public final void ld_global_b8(Register d, Register a, long immOff) {
-        emitString("ld.global.b8" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+        emitString("ld.global.b8" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
     }
 
     public final void ld_global_b16(Register d, Register a, long immOff) {
-        emitString("ld.global.b16" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+        emitString("ld.global.b16" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
     }
 
     public final void ld_global_b32(Register d, Register a, long immOff) {
-        emitString("ld.global.b32" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+        emitString("ld.global.b32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
     }
 
     public final void ld_global_b64(Register d, Register a, long immOff) {
-        emitString("ld.global.b64" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+        emitString("ld.global.b64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
     }
 
     public final void ld_global_u8(Register d, Register a, long immOff) {
-        emitString("ld.global.u8" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+        emitString("ld.global.u8" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
     }
 
     public final void ld_global_u16(Register d, Register a, long immOff) {
-        emitString("ld.global.u16" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+        emitString("ld.global.u16" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
     }
 
     public final void ld_global_u32(Register d, Register a, long immOff) {
-        emitString("ld.global.u32" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+        emitString("ld.global.u32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
     }
 
     public final void ld_global_u64(Register d, Register a, long immOff) {
-        emitString("ld.global.u64" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+        emitString("ld.global.u64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
     }
 
     public final void ld_global_s8(Register d, Register a, long immOff) {
-        emitString("ld.global.s8" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+        emitString("ld.global.s8" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
     }
 
     public final void ld_global_s16(Register d, Register a, long immOff) {
-        emitString("ld.global.s16" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+        emitString("ld.global.s16" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
     }
 
     public final void ld_global_s32(Register d, Register a, long immOff) {
-        emitString("ld.global.s32" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+        emitString("ld.global.s32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
     }
 
     public final void ld_global_s64(Register d, Register a, long immOff) {
-        emitString("ld.global.s64" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+        emitString("ld.global.s64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
     }
 
     public final void ld_global_f32(Register d, Register a, long immOff) {
-        emitString("ld.global.f32" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+        emitString("ld.global.f32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
     }
 
     public final void ld_global_f64(Register d, Register a, long immOff) {
-        emitString("ld.global.f64" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+        emitString("ld.global.f64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
+    }
+
+    // Load from state space to destination register
+    public final void ld_from_state_space(String s, Register d, Register a, long immOff) {
+        emitString("ld" + s + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
+    }
+
+    // Load return address from return parameter which is in .param state space
+    public final void ld_return_address(String s, Register d, Register a, long immOff) {
+        emitString("ld.param." + s + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
     }
 
     public final void mov_b16(Register d, Register a) {
@@ -419,68 +429,68 @@
         emitString("mov.f64" + " " + "%r" + d.encoding() + ", " + f64 + ";" + "");
     }
 
-    public final void mul_f32(Register d, Register a, Register b) {
-        emitString("mul.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    public final void mul_lo_f32(Register d, Register a, Register b) {
+        emitString("mul.lo.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
 
-    public final void mul_f64(Register d, Register a, Register b) {
-        emitString("smul.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    public final void mul_lo_f64(Register d, Register a, Register b) {
+        emitString("mul.lo.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
 
-    public final void mul_s16(Register d, Register a, Register b) {
-        emitString("mul.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    public final void mul_lo_s16(Register d, Register a, Register b) {
+        emitString("mul.lo.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
 
-    public final void mul_s32(Register d, Register a, Register b) {
-        emitString("mul.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    public final void mul_lo_s32(Register d, Register a, Register b) {
+        emitString("mul.lo.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
 
-    public final void mul_s64(Register d, Register a, Register b) {
-        emitString("mul.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    public final void mul_lo_s64(Register d, Register a, Register b) {
+        emitString("mul.lo.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
 
-    public final void mul_s16(Register d, Register a, short s16) {
-        emitString("mul.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + "");
+    public final void mul_lo_s16(Register d, Register a, short s16) {
+        emitString("mul.lo.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + "");
     }
 
-    public final void mul_s32(Register d, Register a, int s32) {
-        emitString("mul.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
+    public final void mul_lo_s32(Register d, Register a, int s32) {
+        emitString("mul.lo.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
     }
 
-    public final void mul_s64(Register d, Register a, long s64) {
-        emitString("mul.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
+    public final void mul_lo_s64(Register d, Register a, long s64) {
+        emitString("mul.lo.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
     }
 
-    public final void mul_f32(Register d, Register a, float f32) {
-        emitString("mul.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + "");
+    public final void mul_lo_f32(Register d, Register a, float f32) {
+        emitString("mul.lo.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + "");
     }
 
-    public final void mul_f64(Register d, Register a, double f64) {
-        emitString("mul.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + "");
+    public final void mul_lo_f64(Register d, Register a, double f64) {
+        emitString("mul.lo.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + "");
     }
 
-    public final void mul_u16(Register d, Register a, Register b) {
-        emitString("mul.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    public final void mul_lo_u16(Register d, Register a, Register b) {
+        emitString("mul.lo.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
 
-    public final void mul_u32(Register d, Register a, Register b) {
-        emitString("mul.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    public final void mul_lo_u32(Register d, Register a, Register b) {
+        emitString("mul.lo.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
 
-    public final void mul_u64(Register d, Register a, Register b) {
-        emitString("mul.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    public final void mul_lo_u64(Register d, Register a, Register b) {
+        emitString("mul.lo.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
 
-    public final void mul_u16(Register d, Register a, short u16) {
-        emitString("mul.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + "");
+    public final void mul_lo_u16(Register d, Register a, short u16) {
+        emitString("mul.lo.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + "");
     }
 
-    public final void mul_u32(Register d, Register a, int u32) {
-        emitString("mul.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    public final void mul_lo_u32(Register d, Register a, int u32) {
+        emitString("mul.lo.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
     }
 
-    public final void mul_u64(Register d, Register a, long u64) {
-        emitString("mul.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
+    public final void mul_lo_u64(Register d, Register a, long u64) {
+        emitString("mul.lo.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
     }
 
     public final void neg_f32(Register d, Register a) {
@@ -539,6 +549,18 @@
         emitString("or.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + "");
     }
 
+    public final void param_8_decl(Register d, boolean lastParam) {
+        emitString(".param" + " " + ".s8" + " " + d + (lastParam ? "" : ","));
+    }
+
+    public final void param_32_decl(Register d, boolean lastParam) {
+        emitString(".param" + " " + ".s32" + " " + d + (lastParam ? "" : ","));
+    }
+
+    public final void param_64_decl(Register d, boolean lastParam) {
+        emitString(".param" + " " + ".s64" + " " + d + (lastParam ? "" : ","));
+    }
+
     public final void popc_b32(Register d, Register a) {
         emitString("popc.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
     }
@@ -827,54 +849,32 @@
         emitString("setp.ge.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + "");
     }
 
-    public final void shl_s16(Register d, Register a, Register b) {
-        emitString("shl.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void shl_s32(Register d, Register a, Register b) {
-        emitString("shl.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    // Shift left - only types supported are .b16, .b32 and .b64
+    public final void shl_b16(Register d, Register a, Register b) {
+        emitString("shl.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
 
-    public final void shl_s64(Register d, Register a, Register b) {
-        emitString("shl.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    public final void shl_b32(Register d, Register a, Register b) {
+        emitString("shl.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
 
-    public final void shl_s16(Register d, Register a, int u32) {
-        emitString("shl.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void shl_s32(Register d, Register a, int u32) {
-        emitString("shl.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void shl_s64(Register d, Register a, int u32) {
-        emitString("shl.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    public final void shl_b64(Register d, Register a, Register b) {
+        emitString("shl.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
 
-    public final void shl_u16(Register d, Register a, Register b) {
-        emitString("shl.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void shl_u32(Register d, Register a, Register b) {
-        emitString("shl.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void shl_u64(Register d, Register a, Register b) {
-        emitString("shl.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    public final void shl_b16_const(Register d, Register a, int b) {
+        emitString("shl.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b + ";" + "");
     }
 
-    public final void shl_u16(Register d, Register a, int u32) {
-        emitString("shl.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    public final void shl_b32_const(Register d, Register a, int b) {
+        emitString("shl.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b + ";" + "");
     }
 
-    public final void shl_u32(Register d, Register a, int u32) {
-        emitString("shl.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    public final void shl_b64_const(Register d, Register a, int b) {
+        emitString("shl.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b + ";" + "");
     }
 
-    public final void shl_u64(Register d, Register a, int u32) {
-        emitString("shl.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
+    // Shift Right instruction
     public final void shr_s16(Register d, Register a, Register b) {
         emitString("shr.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
@@ -923,6 +923,8 @@
         emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
     }
 
+    // Store in global state space
+
     public final void st_global_b8(Register a, long immOff, Register b) {
         emitString("st.global.b8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
     }
@@ -979,6 +981,37 @@
         emitString("st.global.f64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
     }
 
+    // Store return value
+    public final void st_global_return_value_s8(Register a, long immOff, Register b) {
+        emitString("st.global.s8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_return_value_s32(Register a, long immOff, Register b) {
+        emitString("st.global.s32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_return_value_s64(Register a, long immOff, Register b) {
+        emitString("st.global.s64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_return_value_f32(Register a, long immOff, Register b) {
+        emitString("st.global.f32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_return_value_f64(Register a, long immOff, Register b) {
+        emitString("st.global.f64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_return_value_u32(Register a, long immOff, Register b) {
+        emitString("st.global.u32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_return_value_u64(Register a, long immOff, Register b) {
+        emitString("st.global.u64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    // Subtract instruction
+
     public final void sub_f32(Register d, Register a, Register b) {
         emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
     }
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -24,10 +24,11 @@
 
 import java.lang.reflect.Method;
 
-import org.junit.Test;
+import org.junit.*;
 
 public class ArrayTest extends PTXTestBase {
 
+    @Ignore
     @Test
     public void testArray() {
         compile("testArray1I");
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -41,7 +41,7 @@
         invoke(compile("testConstI"));
     }
 
-    public int testConstI() {
+    public static int testConstI() {
         return 42;
     }
 
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.compiler.ptx.test;
 
-import org.junit.Test;
+import org.junit.*;
 
 import java.lang.reflect.Method;
 
 public class ControlTest extends PTXTestBase {
 
+    @Ignore
     @Test
     public void testControl() {
         compile("testSwitch1I");
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/FloatPTXTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/FloatPTXTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -26,18 +26,38 @@
 
 import org.junit.*;
 
+import com.oracle.graal.api.code.CompilationResult;
 
 /* PTX ISA 3.1 - 8.7.3 Floating-Point Instructions */
 public class FloatPTXTest extends PTXTestBase {
 
     @Test
     public void testAdd() {
-        compile("testAdd2F");
-        compile("testAdd2D");
-        compile("testAddFConst");
-        compile("testAddConstF");
-        compile("testAddDConst");
-        compile("testAddConstD");
+        CompilationResult r = compile("testAdd2F");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testAdd2F FAILED");
+        }
+        r = compile("testAdd2D");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testAdd2D FAILED");
+        }
+
+        r = compile("testAddFConst");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testAddFConst FAILED");
+        }
+        r = compile("testAddConstF");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testConstF FAILED");
+        }
+        r = compile("testAddDConst");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testAddDConst FAILED");
+        }
+        r = compile("testAddConstD");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testConstD FAILED");
+        }
     }
 
     public static float testAdd2F(float a, float b) {
@@ -66,12 +86,35 @@
 
     @Test
     public void testSub() {
-        compile("testSub2F");
-        compile("testSub2D");
-        compile("testSubFConst");
-        compile("testSubConstF");
-        compile("testSubDConst");
-        compile("testSubConstD");
+        CompilationResult r = compile("testSub2F");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testSub2F FAILED");
+        }
+
+        r = compile("testSub2D");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testSub2D FAILED");
+        }
+
+        r = compile("testSubFConst");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testSubFConst FAILED");
+        }
+
+        r = compile("testSubConstF");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testSubConstF FAILED");
+        }
+
+        r = compile("testSubDConst");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testSubDconst FAILED");
+        }
+
+        r = compile("testSubConstD");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testConstD FAILED");
+        }
     }
 
     public static float testSub2F(float a, float b) {
@@ -100,12 +143,35 @@
 
     @Test
     public void testMul() {
-        compile("testMul2F");
-        compile("testMul2D");
-        compile("testMulFConst");
-        compile("testMulConstF");
-        compile("testMulDConst");
-        compile("testMulConstD");
+        CompilationResult r = compile("testMul2F");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testAdd2F FAILED");
+        }
+
+        r = compile("testMul2D");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testAdd2F FAILED");
+        }
+
+        r = compile("testMulFConst");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testAdd2F FAILED");
+        }
+
+        r = compile("testMulConstF");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testAdd2F FAILED");
+        }
+
+        r = compile("testMulDConst");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testAdd2F FAILED");
+        }
+
+        r = compile("testMulConstD");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testAdd2F FAILED");
+        }
     }
 
     public static float testMul2F(float a, float b) {
@@ -134,12 +200,35 @@
 
     @Test
     public void testDiv() {
-        compile("testDiv2F");
-        compile("testDiv2D");
-        compile("testDivFConst");
-        compile("testDivConstF");
-        compile("testDivDConst");
-        compile("testDivConstD");
+        CompilationResult r = compile("testDiv2F");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testDiv2F FAILED");
+        }
+
+        r = compile("testDiv2D");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testDiv2D FAILED");
+        }
+
+        r = compile("testDivFConst");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testDivFConst FAILED");
+        }
+
+        r = compile("testDivConstF");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testDivConstF FAILED");
+        }
+
+        r = compile("testDivDConst");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testDivDConst FAILED");
+        }
+
+        r = compile("testDivConstD");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testDivConstD FAILED");
+        }
     }
 
     public static float testDiv2F(float a, float b) {
@@ -168,8 +257,15 @@
 
     @Test
     public void testNeg() {
-        compile("testNeg2F");
-        compile("testNeg2D");
+        CompilationResult r = compile("testNeg2F");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testNeg2F FAILED");
+        }
+
+        r = compile("testNeg2D");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testNeg2D FAILED");
+        }
     }
 
     public static float testNeg2F(float a) {
@@ -195,14 +291,38 @@
         return a % b;
     }
 
+    @Ignore
     @Test
     public void testFloatConversion() {
-        compile("testF2I");
-        compile("testF2L");
-        compile("testF2D");
-        compile("testD2I");
-        compile("testD2L");
-        compile("testD2F");
+        CompilationResult r = compile("testF2I");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of tesF2I FAILED");
+        }
+
+        r = compile("testF2L");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testF2L FAILED");
+        }
+
+        r = compile("testF2D");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testF2D FAILED");
+        }
+
+        r = compile("testD2I");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testD2I FAILED");
+        }
+
+        r = compile("testD2L");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testD2L FAILED");
+        }
+
+        r = compile("testD2F");
+        if (r.getTargetCode() == null) {
+            printReport("Compilation of testD2F FAILED");
+        }
     }
 
     public static int testF2I(float a) {
@@ -229,6 +349,13 @@
         return (float) a;
     }
 
+    public static void printReport(String message) {
+        // CheckStyle: stop system..print check
+        System.out.println(message);
+        // CheckStyle: resume system..print check
+
+    }
+
     public static void main(String[] args) {
         FloatPTXTest test = new FloatPTXTest();
         for (Method m : FloatPTXTest.class.getMethods()) {
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.compiler.ptx.test;
 
-import org.junit.Test;
+import org.junit.*;
 
 import java.lang.reflect.Method;
 
@@ -31,11 +31,45 @@
 
     @Test
     public void testAdd() {
-        invoke(compile("testAdd2I"), 8, 4);
-        invoke(compile("testAdd2L"), 12, 6);
-        invoke(compile("testAdd2B"), 6, 4);
-        invoke(compile("testAddIConst"), 5);
-        invoke(compile("testAddConstI"), 7);
+
+        Integer r4 = (Integer) invoke(compile("testAdd2I"), 18, 24);
+        if (r4 == null) {
+            printReport("testAdd2I FAILED");
+        } else if (r4.intValue() == testAdd2I(18, 24)) {
+            printReport("testAdd2I PASSED");
+        } else {
+            printReport("testAdd2I FAILED");
+        }
+
+        Long r2 = (Long) invoke(compile("testAdd2L"), (long) 12, (long) 6);
+        if (r2 == null) {
+            printReport("testAdd2L FAILED");
+        } else if (r2.longValue() == testAdd2L(12, 6)) {
+            printReport("testAdd2L PASSED");
+        } else {
+            printReport("testAdd2L FAILED");
+        }
+
+        //invoke(compile("testAdd2B"), (byte) 6, (byte) 4);
+
+        r4 = (Integer) invoke(compile("testAddIConst"), 5);
+        if (r4 == null) {
+            printReport("testAddIConst FAILED");
+        } else if (r4.intValue() == testAddIConst(5)) {
+            printReport("testAddIConst PASSED");
+        } else {
+            printReport("testAddIConst FAILED");
+        }
+
+        r4 = (Integer) invoke(compile("testAddConstI"), 7);
+        if (r4 == null) {
+            printReport("testAddConstI FAILED");
+        } else if (r4.intValue() == testAddConstI(7)) {
+            printReport("testAddConstI PASSED");
+        } else {
+            printReport("testAddConstI FAILED");
+        }
+
     }
 
     public static int testAdd2I(int a, int b) {
@@ -60,10 +94,43 @@
 
     @Test
     public void testSub() {
-        invoke(compile("testSub2I"), 8, 4);
-        invoke(compile("testSub2L"), 12, 6);
-        invoke(compile("testSubIConst"), 35);
-        invoke(compile("testSubConstI"), 12);
+
+        Integer r1 = (Integer) invoke(compile("testSub2I"), 18, 4);
+
+        if (r1 == null) {
+            printReport("testSub2I FAILED");
+        } else if (r1.intValue() == testSub2I(18, 4)) {
+            printReport("testSub2I PASSED");
+        } else {
+            printReport("testSub2I FAILED");
+        }
+
+        Long r2 = (Long) invoke(compile("testSub2L"), (long) 12, (long) 6);
+        if (r2 == null) {
+            printReport("testSub2I FAILED (null return value)");
+        } else if (r2.longValue() == testSub2L(12, 6)) {
+            printReport("testSub2I PASSED");
+        } else {
+            printReport("testSub2I FAILED");
+        }
+
+        r1 = (Integer) invoke(compile("testSubIConst"), 35);
+        if (r1 == null) {
+            printReport("testSubIConst FAILED");
+        } else if (r1.intValue() == testSubIConst(35)) {
+            printReport("testSubIConst PASSED");
+        } else {
+            printReport("testSubIConst FAILED");
+        }
+
+        r1 = (Integer) invoke(compile("testSubConstI"), 12);
+        if (r1 == null) {
+            printReport("testSubConstI FAILED");
+        } else if (r1.intValue() == testSubConstI(12)) {
+            printReport("testSubConstI PASSED");
+        } else {
+            printReport("testSubConstI FAILED");
+        }
     }
 
     public static int testSub2I(int a, int b) {
@@ -84,10 +151,42 @@
 
     @Test
     public void testMul() {
-        invoke(compile("testMul2I"), 8, 4);
-        invoke(compile("testMul2L"), 12, 6);
-        invoke(compile("testMulIConst"), 4);
-        invoke(compile("testMulConstI"), 5);
+
+        Integer r1 = (Integer) invoke(compile("testMul2I"), 8, 4);
+        if (r1 == null) {
+            printReport("testMul2I FAILED");
+        } else if (r1.intValue() == testMul2I(8, 4)) {
+            printReport("testMul2I PASSED");
+        } else {
+            printReport("testMul2I FAILED");
+        }
+
+        Long r2 = (Long) invoke(compile("testMul2L"), (long) 12, (long) 6);
+        if (r2 == null) {
+            printReport("testMul2L FAILED");
+        } else if (r2.longValue() == testMul2L(12, 6)) {
+            printReport("testMul2L PASSED");
+        } else {
+            printReport("testMul2L FAILED");
+        }
+
+        r1 = (Integer) invoke(compile("testMulIConst"), 4);
+        if (r1 == null) {
+            printReport("testMulIConst FAILED");
+        } else if (r1.intValue() == testMulIConst(4)) {
+            printReport("testMulIConst PASSED");
+        } else {
+            printReport("testMulIConst FAILED");
+        }
+
+        r1 = (Integer) invoke(compile("testMulConstI"), 5);
+        if (r1 == null) {
+            printReport("testMulConstI FAILED");
+        } else if (r1.intValue() == testMulConstI(5)) {
+            printReport("testMulConstI PASSED");
+        } else {
+            printReport("testMulConstI FAILED");
+        }
     }
 
     public static int testMul2I(int a, int b) {
@@ -108,10 +207,41 @@
 
     @Test
     public void testDiv() {
-        invoke(compile("testDiv2I"), 8, 4);
-        invoke(compile("testDiv2L"), 12, 6);
-        invoke(compile("testDivIConst"), 64);
-        invoke(compile("testDivConstI"), 8);
+        Integer r1 = (Integer) invoke(compile("testDiv2I"), 8, 4);
+        if (r1 == null) {
+            printReport("testDiv2I FAILED (null value returned)");
+        } else if (r1.intValue() == testDiv2I(8, 4)) {
+            printReport("testDiv2I PASSED");
+        } else {
+            printReport("testDiv2I FAILED");
+        }
+
+        Long r2 = (Long) invoke(compile("testDiv2L"), (long) 12, (long) 6);
+        if (r2 == null) {
+            printReport("testDiv2L FAILED (null value returned)");
+        } else if (r2.longValue() == testDiv2L(12, 6)) {
+            printReport("testDiv2L PASSED");
+        } else {
+            printReport("testDiv2L FAILED");
+        }
+
+        r1 = (Integer) invoke(compile("testDivIConst"), 64);
+        if (r1 == null) {
+            printReport("testDivIConst FAILED (null value returned)");
+        } else if (r1.intValue() == testDivIConst(64)) {
+            printReport("testDivIConst PASSED");
+        } else {
+            printReport("testDivIConst FAILED");
+        }
+
+        r1 = (Integer) invoke(compile("testDivConstI"), 8);
+        if (r1 == null) {
+            printReport("testDivConstI FAILED (null value returned)");
+        } else if (r1.intValue() == testDivConstI(8)) {
+            printReport("testDivConstI PASSED");
+        } else {
+            printReport("testDivConstI FAILED");
+        }
     }
 
     public static int testDiv2I(int a, int b) {
@@ -132,8 +262,23 @@
 
     @Test
     public void testRem() {
-        invoke(compile("testRem2I"), 8, 4);
-        invoke(compile("testRem2L"), 12, 6);
+        Integer r1 = (Integer) invoke(compile("testRem2I"), 8, 4);
+        if (r1 == null) {
+            printReport("testRem2I FAILED (null value returned)");
+        } else if (r1.intValue() == testRem2I(8, 4)) {
+            printReport("testRem2I PASSED");
+        } else {
+            printReport("testRem2I FAILED");
+        }
+
+        Long r2 = (Long) invoke(compile("testRem2L"), (long) 12, (long) 6);
+        if (r2 == null) {
+            printReport("testRem2L FAILED (null value returned)");
+        } else if (r1.longValue() == testRem2L(12, 6)) {
+            printReport("testRem2L PASSED");
+        } else {
+            printReport("testRem2L FAILED");
+        }
     }
 
     public static int testRem2I(int a, int b) {
@@ -143,15 +288,31 @@
     public static long testRem2L(long a, long b) {
         return a % b;
     }
-
+    @Ignore
     @Test
     public void testIntConversion() {
-        invoke(compile("testI2L"), 8);
-        invoke(compile("testL2I"), 12L);
-        invoke(compile("testI2C"), 65);
-        invoke(compile("testI2B"), 9);
-        invoke(compile("testI2F"), 17);
-        invoke(compile("testI2D"), 22);
+        Long r1 = (Long) invoke(compile("testI2L"), 8);
+        if (r1 == null) {
+            printReport("testI2L FAILED (null value returned)");
+        } else if (r1.longValue() == testI2L(8)) {
+            printReport("testI2L PASSED");
+        } else {
+            printReport("testI2L FAILED");
+        }
+
+        Integer r2 = (Integer) invoke(compile("testL2I"), (long) 12);
+        if (r2 == null) {
+            printReport("testL2I FAILED (null value returned)");
+        } else if (r1.longValue() == testL2I(12)) {
+            printReport("testL2I PASSED");
+        } else {
+            printReport("testL2I FAILED");
+        }
+
+        // invoke(compile("testI2C"), 65);
+        // invoke(compile("testI2B"), 9);
+        // invoke(compile("testI2F"), 17);
+        // invoke(compile("testI2D"), 22);
     }
 
     public static long testI2L(int a) {
@@ -178,6 +339,13 @@
         return (int) a;
     }
 
+    public static void printReport(String message) {
+        // CheckStyle: stop system..print check
+        System.out.println(message);
+        // CheckStyle: resume system..print check
+
+    }
+
     public static void main(String[] args) {
         IntegerPTXTest test = new IntegerPTXTest();
         for (Method m : IntegerPTXTest.class.getMethods()) {
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -82,11 +82,11 @@
         return sg;
     }
 
-    protected void invoke(CompilationResult result, Object... args) {
+    protected Object invoke(CompilationResult result, Object... args) {
         try {
             if (((ExternalCompilationResult) result).getEntryPoint() == 0) {
                 Debug.dump(result, "[CUDA] *** Null entry point - Not launching kernel");
-                return;
+                return null;
             }
 
             /* Check if the method compiled is static */
@@ -95,9 +95,11 @@
             Object[] executeArgs = argsWithReceiver((isStatic ? null : this), args);
             HotSpotRuntime hsr = (HotSpotRuntime) runtime;
             InstalledCode installedCode = hsr.addExternalMethod(sg.method(), result, sg);
-            installedCode.executeVarargs(executeArgs);
+            Object r = installedCode.executeVarargs(executeArgs);
+            return r;
         } catch (Throwable th) {
             th.printStackTrace();
+            return null;
         }
     }
 }
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,6 +22,10 @@
  */
 package com.oracle.graal.compiler.ptx;
 
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
@@ -32,6 +36,11 @@
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.ptx.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.Block;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
+import com.oracle.graal.graph.GraalInternalError;
 
 /**
  * PTX specific backend.
@@ -84,67 +93,121 @@
         return tasm;
     }
 
-    @Override
-    public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) {
-        // Emit the prologue
+    private static void emitKernelEntry(TargetMethodAssembler tasm, LIRGenerator lirGen,
+                                        ResolvedJavaMethod codeCacheOwner) {
+        // Emit PTX kernel entry text based on PTXParameterOp
+        // instructions in the start block.  Remove the instructions
+        // once kernel entry text and directives are emitted to
+        // facilitate seemless PTX code generation subsequently.
         assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method";
         final String name = codeCacheOwner.getName();
         Buffer codeBuffer = tasm.asm.codeBuffer;
+
+        // Emit initial boiler-plate directives.
         codeBuffer.emitString(".version 1.4");
         codeBuffer.emitString(".target sm_10");
         codeBuffer.emitString0(".entry " + name + " (");
         codeBuffer.emitString("");
 
-        Signature signature = codeCacheOwner.getSignature();
-        int paramCount = signature.getParameterCount(false);
-        // TODO - Revisit this.
-        // Bit-size of registers to be declared and used by the kernel.
-        int regSize = 32;
-        for (int i = 0; i < paramCount; i++) {
-            String param;
-            // No unsigned types in Java. So using .s specifier
-            switch (signature.getParameterKind(i)) {
-                case Boolean:
-                case Byte:
-                    param = ".param .s8 param" + i;
-                    regSize = 8;
-                    break;
-                case Char:
-                case Short:
-                    param = ".param .s16 param" + i;
-                    regSize = 16;
-                    break;
-                case Int:
-                    param = ".param .s32 param" + i;
-                    regSize = 32;
-                    break;
-                case Long:
-                case Float:
-                case Double:
-                case Void:
-                    param = ".param .s64 param" + i;
-                    regSize = 32;
-                    break;
-                default:
-                    // Not sure but specify 64-bit specifier??
-                    param = ".param .s64 param" + i;
-                    break;
+        // Get the start block
+        Block startBlock = lirGen.lir.cfg.getStartBlock();
+        // Keep a list of ParameterOp instructions to delete from the
+        // list of instructions in the block.
+        ArrayList<LIRInstruction> deleteOps = new ArrayList<>();
+
+        // Emit .param arguments to kernel entry based on ParameterOp
+        // instruction.
+        for (LIRInstruction op : lirGen.lir.lir(startBlock)) {
+            if (op instanceof PTXParameterOp) {
+                op.emitCode(tasm);
+                deleteOps.add(op);
             }
-            if (i != (paramCount - 1)) {
-                param += ",";
-            }
-            codeBuffer.emitString(param);
         }
 
+        // Delete ParameterOp instructions.
+        for (LIRInstruction op : deleteOps) {
+            lirGen.lir.lir(startBlock).remove(op);
+        }
+
+        // Start emiting body of the PTX kernel.
         codeBuffer.emitString0(") {");
         codeBuffer.emitString("");
 
-        // XXX For now declare one predicate and all registers
-        codeBuffer.emitString("  .reg .pred %p,%q;");
-        codeBuffer.emitString("  .reg .s" + regSize + " %r<16>;");
+        codeBuffer.emitString(".reg .u64" + " %rax;");
+    }
+
+    // Emit .reg space declarations
+    private static void emitRegisterDecl(TargetMethodAssembler tasm, LIRGenerator lirGen,
+                                         ResolvedJavaMethod codeCacheOwner) {
+        assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method";
+        Buffer codeBuffer = tasm.asm.codeBuffer;
+
+        final SortedSet<Integer> signed32 = new TreeSet<>();
+        final SortedSet<Integer> signed64 = new TreeSet<>();
+
+        ValueProcedure trackRegisterKind = new ValueProcedure() {
+
+            @Override
+            public Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+                if (isRegister(value)) {
+                    RegisterValue regVal = (RegisterValue) value;
+                    Kind regKind = regVal.getKind();
+                    switch (regKind) {
+                       case Int:
+                           signed32.add(regVal.getRegister().encoding());
+                           break;
+                       case Long:
+                           signed64.add(regVal.getRegister().encoding());
+                           break;
+                       default :
+                           throw GraalInternalError.shouldNotReachHere("unhandled register type "  + value.toString());
+                    }
+                }
+                return value;
+            }
+        };
 
+        for (Block b : lirGen.lir.codeEmittingOrder()) {
+            for (LIRInstruction op : lirGen.lir.lir(b)) {
+                op.forEachOutput(trackRegisterKind);
+            }
+        }
+
+        for (Integer i : signed32) {
+            codeBuffer.emitString(".reg .s32 %r" + i.intValue() + ";");
+        }
+        for (Integer i : signed64) {
+            codeBuffer.emitString(".reg .s64 %r" + i.intValue() + ";");
+        }
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) {
+        assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method";
+        Buffer codeBuffer = tasm.asm.codeBuffer;
+        // Emit the prologue
+        emitKernelEntry(tasm, lirGen, codeCacheOwner);
+
+        // Emit register declarations
+        try {
+            emitRegisterDecl(tasm, lirGen, codeCacheOwner);
+        } catch (GraalInternalError e) {
+            // TODO : Better error handling needs to be done once
+            //        all types of parameters are handled.
+            codeBuffer.setPosition(0);
+            codeBuffer.close(false);
+            return;
+        }
         // Emit code for the LIR
-        lirGen.lir.emitCode(tasm);
+        try {
+            lirGen.lir.emitCode(tasm);
+        } catch (GraalInternalError e) {
+            // TODO : Better error handling needs to be done once
+            //        all types of parameters are handled.
+            codeBuffer.setPosition(0);
+            codeBuffer.close(false);
+            return;
+        }
 
         // Emit the epilogue
         codeBuffer.emitString0("}");
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Tue Sep 10 16:33:28 2013 -0700
@@ -47,12 +47,16 @@
 import com.oracle.graal.lir.ptx.PTXControlFlow.CondMoveOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.FloatCondMoveOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp;
+import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnNoValOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.SequentialSwitchOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.TableSwitchOp;
-import com.oracle.graal.lir.ptx.PTXMove.LoadOp;
 import com.oracle.graal.lir.ptx.PTXMove.MoveFromRegOp;
 import com.oracle.graal.lir.ptx.PTXMove.MoveToRegOp;
-import com.oracle.graal.lir.ptx.PTXMove.StoreOp;
+import com.oracle.graal.lir.ptx.PTXMemOp.LoadOp;
+import com.oracle.graal.lir.ptx.PTXMemOp.StoreOp;
+import com.oracle.graal.lir.ptx.PTXMemOp.LoadParamOp;
+import com.oracle.graal.lir.ptx.PTXMemOp.LoadReturnAddrOp;
+import com.oracle.graal.lir.ptx.PTXMemOp.StoreReturnValOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
@@ -96,6 +100,42 @@
         }
     }
 
+    protected static AllocatableValue toParamKind(AllocatableValue value) {
+        if (value.getKind().getStackKind() != value.getKind()) {
+            // We only have stack-kinds in the LIR, so convert the operand kind for values from the
+            // calling convention.
+            if (isRegister(value)) {
+                return asRegister(value).asValue(value.getKind().getStackKind());
+            } else if (isStackSlot(value)) {
+                return StackSlot.get(value.getKind().getStackKind(), asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize());
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+        return value;
+    }
+
+    @Override
+    public void emitPrologue() {
+        // Need to emit .param directives based on incoming arguments and return value
+        CallingConvention incomingArguments = cc;
+        int argCount = incomingArguments.getArgumentCount();
+        // Additional argument for return value.
+        Value[] params = new Value[argCount + 1];
+        for (int i = 0; i < argCount; i++) {
+            params[i] = toParamKind(incomingArguments.getArgument(i));
+        }
+        // Add the return value as the last parameter.
+        params[argCount] =  incomingArguments.getReturn();
+
+        append(new PTXParameterOp(params));
+        for (LocalNode local : graph.getNodes(LocalNode.class)) {
+            Value param = params[local.index()];
+            assert param.getKind() == local.kind().getStackKind();
+            setResult(local, emitLoadParam(param.getKind(), param, null));
+        }
+    }
+
     @Override
     public Variable emitMove(Value input) {
         Variable result = newVariable(input.getKind());
@@ -250,7 +290,8 @@
     /**
      * This method emits the compare instruction, and may reorder the operands. It returns true if
      * it did so.
-     * 
+     *
+     *
      * @param a the left operand of the comparison
      * @param b the right operand of the comparison
      * @return true if the left and right operands were switched, false otherwise
@@ -705,6 +746,10 @@
         append(new ReturnOp(input));
     }
 
+    private void emitReturnNoVal() {
+        append(new ReturnNoValOp());
+    }
+
     @Override
     protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
         // Making a copy of the switch value is necessary because jump table destroys the input
@@ -761,4 +806,38 @@
     public void visitInfopointNode(InfopointNode i) {
         throw new InternalError("NYI");
     }
+
+    public Variable emitLoadParam(Kind kind, Value address, DeoptimizingNode deopting) {
+        PTXAddressValue loadAddress = asAddress(address);
+        Variable result = newVariable(kind);
+        append(new LoadParamOp(kind, result, loadAddress, deopting != null ? state(deopting) : null));
+        return result;
+    }
+
+    public Variable emitLoadReturnAddress(Kind kind, Value address, DeoptimizingNode deopting) {
+        PTXAddressValue loadAddress = asAddress(address);
+        Variable result = newVariable(kind);
+        append(new LoadReturnAddrOp(kind, result, loadAddress, deopting != null ? state(deopting) : null));
+        return result;
+    }
+
+    public void emitStoreReturnValue(Kind kind, Value address, Value inputVal, DeoptimizingNode deopting) {
+        PTXAddressValue storeAddress = asAddress(address);
+        Variable input = load(inputVal);
+        append(new StoreReturnValOp(kind, storeAddress, input, deopting != null ? state(deopting) : null));
+    }
+
+
+    @Override
+    public void visitReturn(ReturnNode x) {
+        AllocatableValue operand = Value.ILLEGAL;
+        if (x.result() != null) {
+            operand = resultOperandFor(x.result().kind());
+            // Load the global memory address from return parameter
+            Variable loadVar = emitLoadReturnAddress(operand.getKind(), operand, null);
+            // Store result in global memory whose location is loadVar
+            emitStoreReturnValue(operand.getKind(), loadVar, operand(x.result()), null);
+        }
+        emitReturnNoVal();
+    }
 }
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXTargetMethodAssembler.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXTargetMethodAssembler.java	Tue Sep 10 16:33:28 2013 -0700
@@ -50,7 +50,7 @@
         ExternalCompilationResult graalCompile = (ExternalCompilationResult) super.finishTargetMethod(graph);
 
         try {
-            if (validDevice) {
+            if ((validDevice) && (graalCompile.getTargetCode() != null)) {
                 long kernel = toGPU.generateKernel(graalCompile.getTargetCode(), method.getName());
                 graalCompile.setEntryPoint(kernel);
             }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -308,8 +308,8 @@
         graph = parse(snippet);
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-        new InliningPhase().apply(graph, context);
-        new PartialEscapePhase(false).apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
+        new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context);
     }
 
     private void compareGraphs(final String snippet, final String referenceSnippet) {
@@ -326,19 +326,19 @@
                 Assumptions assumptions = new Assumptions(false);
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
                 CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
-                new InliningPhase().apply(graph, context);
+                new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 if (loopPeeling) {
                     new LoopTransformHighPhase().apply(graph);
                 }
                 new DeadCodeEliminationPhase().apply(graph);
                 canonicalizer.apply(graph, context);
-                new PartialEscapePhase(false).apply(graph, context);
+                new PartialEscapePhase(false, canonicalizer).apply(graph, context);
 
                 new DeadCodeEliminationPhase().apply(graph);
                 canonicalizer.apply(graph, context);
 
                 StructuredGraph referenceGraph = parse(referenceSnippet);
-                new InliningPhase().apply(referenceGraph, context);
+                new InliningPhase(new CanonicalizerPhase(true)).apply(referenceGraph, context);
                 new DeadCodeEliminationPhase().apply(referenceGraph);
                 new CanonicalizerPhase(true).apply(referenceGraph, context);
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -30,12 +30,13 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 public class CompareCanonicalizerTest extends GraalCompilerTest {
 
     private StructuredGraph getCanonicalizedGraph(String name) {
         StructuredGraph graph = parse(name);
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         return graph;
     }
 
@@ -53,7 +54,7 @@
             assertEquals(referenceGraph, graph);
         }
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(referenceGraph);
+        new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(runtime(), assumptions, replacements));
         for (int i = 1; i < 4; i++) {
             StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i);
             assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -32,6 +32,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
  * Collection of tests for {@link ConditionalEliminationPhase} including those that triggered bugs
@@ -141,7 +142,7 @@
 
         StructuredGraph graph = parse("testNullnessSnippet");
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         for (ConstantNode constant : graph.getNodes().filter(ConstantNode.class)) {
             assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0);
         }
@@ -163,7 +164,7 @@
     @Test
     public void testDisjunction() {
         StructuredGraph graph = parse("testDisjunctionSnippet");
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         IfNode ifNode = (IfNode) graph.start().next();
         InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition();
         IsNullNode x = graph.unique(new IsNullNode(graph.getLocal(0)));
@@ -171,9 +172,9 @@
         ShortCircuitOrNode disjunction = graph.unique(new ShortCircuitOrNode(x, false, y, false, NOT_FREQUENT_PROBABILITY));
         LogicNegationNode negation = graph.unique(new LogicNegationNode(disjunction));
         ifNode.setCondition(negation);
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         for (ConstantNode constant : graph.getNodes().filter(ConstantNode.class)) {
             assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0);
         }
@@ -191,7 +192,7 @@
     public void testInvoke() {
         test("testInvokeSnippet", new Integer(16));
         StructuredGraph graph = parse("testInvokeSnippet");
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         new ConditionalEliminationPhase(runtime()).apply(graph);
 
         InvokeNode invoke = graph.getNodes(InvokeNode.class).first();
@@ -221,9 +222,9 @@
     @Test
     public void testTypeMerging() {
         StructuredGraph graph = parse("testTypeMergingSnippet");
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
 
         assertEquals(0, graph.getNodes().filter(StoreFieldNode.class).count());
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -83,7 +83,7 @@
             public void run() {
                 StructuredGraph graph = parse(snippet);
                 HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-                new InliningPhase().apply(graph, context);
+                new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 new CanonicalizerPhase(true).apply(graph, context);
                 Debug.dump(graph, "Graph");
                 StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -31,6 +31,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 public class EliminateNestedCheckCastsTest extends GraalCompilerTest {
 
@@ -113,7 +114,7 @@
             public StructuredGraph call() throws Exception {
                 Debug.dump(graph, "After parsing: " + snippet);
                 Assert.assertEquals(checkcasts, graph.getNodes().filter(CheckCastNode.class).count());
-                new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
+                new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements));
                 Assert.assertEquals(afterCanon, graph.getNodes(CheckCastNode.class).count());
                 return graph;
             }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -69,7 +69,7 @@
         GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault();
         new GraphBuilderPhase(runtime, conf, OptimisticOptimizations.ALL).apply(graph);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-        new InliningPhase().apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
         return graph;
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -29,7 +29,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -60,7 +59,7 @@
             public void run() {
                 StructuredGraph graph = parse(snippet);
                 PhaseContext context = new PhaseContext(runtime(), new Assumptions(false), replacements);
-                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 new FloatingReadPhase().apply(graph);
 
                 ReturnNode returnNode = null;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -87,7 +87,7 @@
     }
 
     @BeforeClass
-    public static void initializeDebgging() {
+    public static void initializeDebugging() {
         DebugEnvironment.initialize(System.out);
     }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -31,6 +31,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
  * In the following tests, the usages of local variable "a" are replaced with the integer constant
@@ -144,7 +145,10 @@
             n.replaceFirstInput(local, constant);
         }
         Debug.dump(graph, "Graph");
-        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements));
+        for (FrameState fs : local.usages().filter(FrameState.class).snapshot()) {
+            fs.replaceFirstInput(local, null);
+        }
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -67,7 +67,7 @@
         }
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-        new InliningPhase(hints).apply(graph, context);
+        new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
         new DeadCodeEliminationPhase().apply(graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -78,7 +78,7 @@
 
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-        new InliningPhase(hints).apply(graph, context);
+        new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
         new DeadCodeEliminationPhase().apply(graph);
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -29,7 +29,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -62,7 +61,7 @@
         test("testSynchronizedSnippet", new A(), new A());
 
         StructuredGraph graph = getGraph("testSynchronizedSnippet");
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         new LockEliminationPhase().apply(graph);
         assertEquals(1, graph.getNodes().filter(MonitorEnterNode.class).count());
         assertEquals(1, graph.getNodes().filter(MonitorExitNode.class).count());
@@ -80,7 +79,7 @@
         test("testSynchronizedMethodSnippet", new A());
 
         StructuredGraph graph = getGraph("testSynchronizedMethodSnippet");
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         new LockEliminationPhase().apply(graph);
         assertEquals(1, graph.getNodes().filter(MonitorEnterNode.class).count());
         assertEquals(1, graph.getNodes().filter(MonitorExitNode.class).count());
@@ -93,10 +92,10 @@
         Assumptions assumptions = new Assumptions(true);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, phasePlan, OptimisticOptimizations.ALL);
         new CanonicalizerPhase(true).apply(graph, context);
-        new InliningPhase().apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
         new DeadCodeEliminationPhase().apply(graph);
-        new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
+        new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context);
         new ValueAnchorCleanupPhase().apply(graph);
         new LockEliminationPhase().apply(graph);
         return graph;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -30,6 +30,7 @@
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 public class LoopUnswitchTest extends GraalCompilerTest {
 
@@ -133,8 +134,8 @@
         }
 
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(referenceGraph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
+        new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(runtime(), assumptions, replacements));
         Debug.scope("Test", new DebugDumpScope("Test:" + snippet), new Runnable() {
 
             @Override
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -36,7 +36,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
@@ -502,9 +501,9 @@
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
                 new CanonicalizerPhase(true).apply(graph, context);
                 if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
-                    new InliningPhase().apply(graph, context);
+                    new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 }
-                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
                     for (Node node : graph.getNodes()) {
                         if (node instanceof StateSplit) {
@@ -523,8 +522,8 @@
 
                 MidTierContext midContext = new MidTierContext(runtime(), assumptions, replacements, runtime().getTarget(), OptimisticOptimizations.ALL);
                 new GuardLoweringPhase().apply(graph, midContext);
-                new LoweringPhase(LoweringType.AFTER_GUARDS).apply(graph, midContext);
-                new LoweringPhase(LoweringType.AFTER_FSA).apply(graph, midContext);
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, midContext);
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, midContext);
 
                 SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, memsched);
                 schedule.apply(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -95,7 +95,7 @@
         }
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-        new InliningPhase(hints).apply(graph, context);
+        new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
         new DeadCodeEliminationPhase().apply(graph);
         return graph;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -30,7 +30,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -94,7 +93,7 @@
         StructuredGraph graph = parse(snippet);
         PhaseContext context = new PhaseContext(runtime(), new Assumptions(false), replacements);
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
-        new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
+        new LoweringPhase(canonicalizer).apply(graph, context);
         canonicalizer.apply(graph, context);
         new PushThroughPiPhase().apply(graph);
         canonicalizer.apply(graph, context);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -29,7 +29,6 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -85,7 +84,7 @@
             public void run() {
                 StructuredGraph graph = parse(snippet);
                 PhaseContext context = new PhaseContext(runtime(), new Assumptions(false), replacements);
-                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 new FloatingReadPhase().apply(graph);
                 new EliminatePartiallyRedundantGuardsPhase(true, false).apply(graph);
                 new ReadEliminationPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 public class ReassociateAndCanonicalTest extends GraalCompilerTest {
 
@@ -244,9 +245,9 @@
     private <T extends Node & Node.IterableNodeType> void test(String test, String ref) {
         StructuredGraph testGraph = parse(test);
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(testGraph);
+        new CanonicalizerPhase(true).apply(testGraph, new PhaseContext(runtime(), assumptions, replacements));
         StructuredGraph refGraph = parse(ref);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(refGraph);
+        new CanonicalizerPhase(true).apply(refGraph, new PhaseContext(runtime(), assumptions, replacements));
         assertEquals(testGraph, refGraph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
  * In the following tests, the scalar type system of the compiler should be complete enough to see
@@ -166,9 +167,9 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
         StructuredGraph referenceGraph = parse(referenceSnippet);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
  * This class tests some specific patterns the stamp system should be able to canonicalize away
@@ -109,7 +110,7 @@
 
     private void testZeroReturn(String methodName) {
         StructuredGraph graph = parse(methodName);
-        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements));
         new DeadCodeEliminationPhase().apply(graph);
         assertConstantReturn(graph, 0);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 public class StraighteningTest extends GraalCompilerTest {
 
@@ -89,7 +90,7 @@
         // No debug scope to reduce console noise for @Test(expected = ...) tests
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
-        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements));
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -35,6 +35,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
  * In the following tests, the scalar type system of the compiler should be complete enough to see
@@ -184,13 +185,13 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
         // a second canonicalizer is needed to process nested MaterializeNodes
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
         StructuredGraph referenceGraph = parse(referenceSnippet);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(referenceGraph);
+        new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(runtime(), assumptions, replacements));
         assertEquals(referenceGraph, graph);
     }
 
@@ -240,9 +241,9 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
         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/deopt/CompiledMethodTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -32,6 +32,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.test.*;
 
 /**
@@ -55,7 +56,7 @@
     public void test1() {
         Method method = getMethod("testMethod");
         final StructuredGraph graph = parse(method);
-        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements));
         new DeadCodeEliminationPhase().apply(graph);
 
         for (Node node : graph.getNodes()) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -42,7 +42,7 @@
         graph = parse(snippet);
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-        new InliningPhase().apply(graph, context);
-        new EarlyReadEliminationPhase().apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
+        new EarlyReadEliminationPhase(new CanonicalizerPhase(true)).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -234,10 +234,10 @@
 
                 Assumptions assumptions = new Assumptions(false);
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-                new InliningPhase().apply(graph, context);
+                new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 new DeadCodeEliminationPhase().apply(graph);
                 new CanonicalizerPhase(true).apply(graph, context);
-                new PartialEscapePhase(iterativeEscapeAnalysis).apply(graph, context);
+                new PartialEscapePhase(iterativeEscapeAnalysis, new CanonicalizerPhase(true)).apply(graph, context);
                 Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count());
                 ReturnNode returnNode = graph.getNodes(ReturnNode.class).first();
                 if (expectedConstantResult != null) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -244,7 +244,7 @@
         graph = parse(snippet);
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-        new InliningPhase().apply(graph, context);
-        new PartialEscapePhase(false, true).apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
+        new PartialEscapePhase(false, true, new CanonicalizerPhase(true)).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -199,10 +199,10 @@
 
                 Assumptions assumptions = new Assumptions(false);
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-                new InliningPhase().apply(graph, context);
+                new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 new DeadCodeEliminationPhase().apply(graph);
                 new CanonicalizerPhase(true).apply(graph, context);
-                new PartialEscapePhase(false).apply(graph, context);
+                new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context);
 
                 for (MergeNode merge : graph.getNodes(MergeNode.class)) {
                     merge.setStateAfter(null);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -240,7 +240,7 @@
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, phasePlan, OptimisticOptimizations.ALL);
                 Debug.dump(graph, "Graph");
                 new CanonicalizerPhase(true).apply(graph, context);
-                new InliningPhase().apply(graph, context);
+                new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 Debug.dump(graph, "Graph");
                 new CanonicalizerPhase(true).apply(graph, context);
                 new DeadCodeEliminationPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.compiler;
 
+import static com.oracle.graal.compiler.GraalCompiler.Options.*;
+import static com.oracle.graal.compiler.MethodFilter.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
@@ -34,12 +36,14 @@
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.common.*;
@@ -52,6 +56,71 @@
  */
 public class GraalCompiler {
 
+    private static final DebugTimer FrontEnd = Debug.timer("FrontEnd");
+    private static final DebugTimer BackEnd = Debug.timer("BackEnd");
+
+    /**
+     * The set of positive filters specified by the {@code -G:IntrinsificationsEnabled} option. To
+     * enable a fast path in {@link #shouldIntrinsify(JavaMethod)}, this field is {@code null} when
+     * no enabling/disabling filters are specified.
+     */
+    private static final MethodFilter[] positiveIntrinsificationFilter;
+
+    /**
+     * The set of negative filters specified by the {@code -G:IntrinsificationsDisabled} option.
+     */
+    private static final MethodFilter[] negativeIntrinsificationFilter;
+
+    static class Options {
+
+        // @formatter:off
+        /**
+         * @see MethodFilter
+         */
+        @Option(help = "Pattern for method(s) to which intrinsification (if available) will be applied. " +
+                       "By default, all available intrinsifications are applied except for methods matched " +
+                       "by IntrinsificationsDisabled. See MethodFilter class for pattern syntax.")
+        public static final OptionValue<String> IntrinsificationsEnabled = new OptionValue<>(null);
+        /**
+         * @see MethodFilter
+         */
+        @Option(help = "Pattern for method(s) to which intrinsification will not be applied. " +
+                       "See MethodFilter class for pattern syntax.")
+        public static final OptionValue<String> IntrinsificationsDisabled = new OptionValue<>("Object.clone");
+        // @formatter:on
+
+    }
+
+    static {
+        if (IntrinsificationsDisabled.getValue() != null) {
+            negativeIntrinsificationFilter = parse(IntrinsificationsDisabled.getValue());
+        } else {
+            negativeIntrinsificationFilter = null;
+        }
+
+        if (Options.IntrinsificationsEnabled.getValue() != null) {
+            positiveIntrinsificationFilter = parse(IntrinsificationsEnabled.getValue());
+        } else if (negativeIntrinsificationFilter != null) {
+            positiveIntrinsificationFilter = new MethodFilter[0];
+        } else {
+            positiveIntrinsificationFilter = null;
+        }
+    }
+
+    /**
+     * Determines if a given method should be intrinsified based on the values of
+     * {@link Options#IntrinsificationsEnabled} and {@link Options#IntrinsificationsDisabled}.
+     */
+    public static boolean shouldIntrinsify(JavaMethod method) {
+        if (positiveIntrinsificationFilter == null) {
+            return true;
+        }
+        if (positiveIntrinsificationFilter.length == 0 || matches(positiveIntrinsificationFilter, method)) {
+            return negativeIntrinsificationFilter == null || !matches(negativeIntrinsificationFilter, method);
+        }
+        return false;
+    }
+
     /**
      * Requests compilation of a given graph.
      * 
@@ -62,13 +131,9 @@
      *            argument can be null.
      * @return the result of the compilation
      */
-    public static CompilationResult compileGraph(final StructuredGraph graph, final CallingConvention cc,
-                                                 final ResolvedJavaMethod installedCodeOwner, final GraalCodeCacheProvider runtime,
-                                                 final Replacements replacements, final Backend backend,
-                                                 final TargetDescription target, final GraphCache cache,
-                                                 final PhasePlan plan, final OptimisticOptimizations optimisticOpts,
-                                                 final SpeculationLog speculationLog, final Suites suites,
-                                                 final CompilationResult compilationResult) {
+    public static CompilationResult compileGraph(final StructuredGraph graph, final CallingConvention cc, final ResolvedJavaMethod installedCodeOwner, final GraalCodeCacheProvider runtime,
+                    final Replacements replacements, final Backend backend, final TargetDescription target, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts,
+                    final SpeculationLog speculationLog, final Suites suites, final CompilationResult compilationResult) {
         Debug.scope("GraalCompiler", new Object[]{graph, runtime}, new Runnable() {
 
             public void run() {
@@ -76,22 +141,26 @@
                 final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() {
 
                     public LIR call() {
-                        return emitHIR(runtime, target, graph, replacements, assumptions, cache, plan, optimisticOpts, speculationLog, suites);
+                        try (TimerCloseable a = FrontEnd.start()) {
+                            return emitHIR(runtime, target, graph, replacements, assumptions, cache, plan, optimisticOpts, speculationLog, suites);
+                        }
                     }
                 });
-                final LIRGenerator lirGen = Debug.scope("BackEnd", lir, new Callable<LIRGenerator>() {
+                try (TimerCloseable a = BackEnd.start()) {
+                    final LIRGenerator lirGen = Debug.scope("BackEnd", lir, new Callable<LIRGenerator>() {
 
-                    public LIRGenerator call() {
-                        return emitLIR(backend, target, lir, graph, cc);
-                    }
-                });
-                Debug.scope("CodeGen", lirGen, new Runnable() {
+                        public LIRGenerator call() {
+                            return emitLIR(backend, target, lir, graph, cc);
+                        }
+                    });
+                    Debug.scope("CodeGen", lirGen, new Runnable() {
 
-                    public void run() {
-                        emitCode(backend, getLeafGraphIdArray(graph), assumptions, lirGen, compilationResult, installedCodeOwner);
-                    }
+                        public void run() {
+                            emitCode(backend, getLeafGraphIdArray(graph), assumptions, lirGen, compilationResult, installedCodeOwner);
+                        }
 
-                });
+                    });
+                }
             }
         });
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Tue Sep 10 16:33:28 2013 -0700
@@ -36,17 +36,15 @@
 public class GraalDebugConfig implements DebugConfig {
 
     // @formatter:off
-    @Option(help = "Enable scope-based debugging", name = "Debug")
-    public static final OptionValue<Boolean> DebugEnabled = new OptionValue<>(true);
-    @Option(help = "Scopes to be dumped")
+    @Option(help = "Pattern for scope(s) to in which dumping is enabled (see DebugFilter and Debug.dump)")
     public static final OptionValue<String> Dump = new OptionValue<>(null);
-    @Option(help = "Scopes to be metered")
+    @Option(help = "Pattern for scope(s) to in which metering is enabled (see DebugFilter and Debug.metric)")
     public static final OptionValue<String> Meter = new OptionValue<>(null);
-    @Option(help = "Scopes to be timed")
+    @Option(help = "Pattern for scope(s) to in which timing is enabled (see DebugFilter and Debug.timer)")
     public static final OptionValue<String> Time = new OptionValue<>(null);
-    @Option(help = "Scopes to be logged")
+    @Option(help = "Pattern for scope(s) to in which logging is enabled (see DebugFilter and Debug.log)")
     public static final OptionValue<String> Log = new OptionValue<>(null);
-    @Option(help = "Filters debug scope output by method name/pattern")
+    @Option(help = "Pattern for filtering debug scope output based on method context (see MethodFilter)")
     public static final OptionValue<String> MethodFilter = new OptionValue<>(null);
     @Option(help = "How to print metric and timing values:%n" +
                    "Name - aggregate by unqualified name%n" +
@@ -68,6 +66,10 @@
     };
     // @formatter:on
 
+    public static boolean areDebugScopePatternsEnabled() {
+        return DumpOnError.getValue() || Dump.getValue() != null || Meter.getValue() != null || Time.getValue() != null || Log.getValue() != null;
+    }
+
     private final DebugFilter logFilter;
     private final DebugFilter meterFilter;
     private final DebugFilter timerFilter;
@@ -85,11 +87,7 @@
         if (methodFilter == null || methodFilter.isEmpty()) {
             this.methodFilter = null;
         } else {
-            String[] filters = methodFilter.split(",");
-            this.methodFilter = new MethodFilter[filters.length];
-            for (int i = 0; i < filters.length; i++) {
-                this.methodFilter[i] = new MethodFilter(filters[i]);
-            }
+            this.methodFilter = com.oracle.graal.compiler.MethodFilter.parse(methodFilter);
         }
 
         // Report the filters that have been configured so the user can verify it's what they expect
@@ -156,10 +154,8 @@
                 } else if (methodFilter != null) {
                     JavaMethod method = asJavaMethod(o);
                     if (method != null) {
-                        for (MethodFilter filter : methodFilter) {
-                            if (filter.matches(method)) {
-                                return true;
-                            }
+                        if (com.oracle.graal.compiler.MethodFilter.matches(methodFilter, method)) {
+                            return true;
                         }
                     }
                 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/MethodFilter.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/MethodFilter.java	Tue Sep 10 16:33:28 2013 -0700
@@ -88,6 +88,31 @@
     private final Pattern methodName;
     private final Pattern[] signature;
 
+    /**
+     * Parses a string containing list of comma separated filter patterns into an array of
+     * {@link MethodFilter}s.
+     */
+    public static MethodFilter[] parse(String commaSeparatedPatterns) {
+        String[] filters = commaSeparatedPatterns.split(",");
+        MethodFilter[] methodFilters = new MethodFilter[filters.length];
+        for (int i = 0; i < filters.length; i++) {
+            methodFilters[i] = new MethodFilter(filters[i]);
+        }
+        return methodFilters;
+    }
+
+    /**
+     * Determines if a given method is matched by a given array of filters.
+     */
+    public static boolean matches(MethodFilter[] filters, JavaMethod method) {
+        for (MethodFilter filter : filters) {
+            if (filter.matches(method)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     public MethodFilter(String sourcePattern) {
         String pattern = sourcePattern.trim();
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Tue Sep 10 16:33:28 2013 -0700
@@ -686,9 +686,8 @@
             List<LIRInstruction> instructions = ir.lir(block);
             int numInst = instructions.size();
 
-            // iterate all instructions of the block. skip the first because it is always a label
-            assert !instructions.get(0).hasOperands() : "first operation must always be a label";
-            for (int j = 1; j < numInst; j++) {
+            // iterate all instructions of the block
+            for (int j = 0; j < numInst; j++) {
                 final LIRInstruction op = instructions.get(j);
 
                 ValueProcedure useProc = new ValueProcedure() {
@@ -1174,10 +1173,8 @@
             }
 
             // iterate all instructions of the block in reverse order.
-            // skip the first instruction because it is always a label
             // definitions of intervals are processed before uses
-            assert !instructions.get(0).hasOperands() : "first operation must always be a label";
-            for (int j = instructions.size() - 1; j >= 1; j--) {
+            for (int j = instructions.size() - 1; j >= 0; j--) {
                 final LIRInstruction op = instructions.get(j);
                 final int opId = op.id();
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Tue Sep 10 16:33:28 2013 -0700
@@ -40,7 +40,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.JumpOp;
 import com.oracle.graal.lir.StandardOp.LabelOp;
-import com.oracle.graal.lir.StandardOp.ParametersOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
@@ -405,7 +404,7 @@
     }
 
     public void emitIncomingValues(Value[] params) {
-        append(new ParametersOp(params));
+        ((LabelOp) lir.lir(currentBlock).get(0)).setIncomingValues(params);
     }
 
     @Override
@@ -452,12 +451,16 @@
         append(new JumpOp(getLIRBlock(merge)));
     }
 
+    protected PlatformKind getPhiKind(PhiNode phi) {
+        return phi.kind();
+    }
+
     private Value operandForPhi(PhiNode phi) {
         assert phi.type() == PhiType.Value : "wrong phi type: " + phi;
         Value result = operand(phi);
         if (result == null) {
             // allocate a variable for this phi
-            Variable newOperand = newVariable(phi.kind());
+            Variable newOperand = newVariable(getPhiKind(phi));
             setResult(phi, newOperand);
             return newOperand;
         } else {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java	Tue Sep 10 16:33:28 2013 -0700
@@ -230,7 +230,7 @@
 
     private void moveToTemp(Value src) {
         assert isIllegal(temp);
-        temp = gen.newVariable(src.getKind());
+        temp = gen.newVariable(src.getPlatformKind());
         emitMove(temp, src);
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,12 +22,12 @@
  */
 package com.oracle.graal.compiler.phases;
 
+import static com.oracle.graal.compiler.phases.HighTier.Options.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.loop.phases.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
@@ -37,12 +37,15 @@
 
 public class HighTier extends PhaseSuite<HighTierContext> {
 
-    // @formatter:off
-    @Option(help = "")
-    public static final OptionValue<Boolean> VerifyUsageWithEquals = new OptionValue<>(true);
-    @Option(help = "Enable inlining")
-    public static final OptionValue<Boolean> Inline = new OptionValue<>(true);
-    // @formatter:on
+    static class Options {
+
+        // @formatter:off
+        @Option(help = "")
+        public static final OptionValue<Boolean> VerifyUsageWithEquals = new OptionValue<>(true);
+        @Option(help = "Enable inlining")
+        public static final OptionValue<Boolean> Inline = new OptionValue<>(true);
+        // @formatter:on
+    }
 
     public HighTier() {
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue());
@@ -60,12 +63,12 @@
             if (IterativeInlining.getValue()) {
                 appendPhase(new IterativeInliningPhase(canonicalizer));
             } else {
-                appendPhase(new InliningPhase());
+                appendPhase(new InliningPhase(canonicalizer));
                 appendPhase(new DeadCodeEliminationPhase());
 
                 if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
                     appendPhase(canonicalizer);
-                    appendPhase(new IterativeConditionalEliminationPhase());
+                    appendPhase(new IterativeConditionalEliminationPhase(canonicalizer));
                 }
             }
         }
@@ -73,15 +76,15 @@
         appendPhase(new CleanTypeProfileProxyPhase());
 
         if (FullUnroll.getValue()) {
-            appendPhase(new LoopFullUnrollPhase(!AOTCompilation.getValue()));
+            appendPhase(new LoopFullUnrollPhase(canonicalizer));
         }
 
         if (OptTailDuplication.getValue()) {
-            appendPhase(new TailDuplicationPhase());
+            appendPhase(new TailDuplicationPhase(canonicalizer));
         }
 
         if (PartialEscapeAnalysis.getValue()) {
-            appendPhase(new PartialEscapePhase(true));
+            appendPhase(new PartialEscapePhase(true, canonicalizer));
         }
 
         if (OptConvertDeoptsToGuards.getValue()) {
@@ -98,6 +101,6 @@
             appendPhase(canonicalizer);
         }
 
-        appendPhase(new LoweringPhase(LoweringType.BEFORE_GUARDS));
+        appendPhase(new LoweringPhase(canonicalizer));
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,7 +22,8 @@
  */
 package com.oracle.graal.compiler.phases;
 
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -30,7 +31,9 @@
 public class LowTier extends PhaseSuite<LowTierContext> {
 
     public LowTier() {
-        appendPhase(new LoweringPhase(LoweringType.AFTER_FSA));
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue());
+
+        appendPhase(new LoweringPhase(canonicalizer));
 
         appendPhase(new ExpandLogicPhase());
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Tue Sep 10 16:33:28 2013 -0700
@@ -25,7 +25,6 @@
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import com.oracle.graal.loop.phases.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -47,11 +46,11 @@
         appendPhase(new LockEliminationPhase());
 
         if (OptReadElimination.getValue()) {
-            appendPhase(new EarlyReadEliminationPhase());
+            appendPhase(new EarlyReadEliminationPhase(canonicalizer));
         }
 
         if (OptFloatingReads.getValue()) {
-            IncrementalCanonicalizerPhase<MidTierContext> incCanonicalizer = new IncrementalCanonicalizerPhase<>();
+            IncrementalCanonicalizerPhase<MidTierContext> incCanonicalizer = new IncrementalCanonicalizerPhase<>(canonicalizer);
             incCanonicalizer.appendPhase(new FloatingReadPhase());
             appendPhase(incCanonicalizer);
             if (OptReadElimination.getValue()) {
@@ -69,7 +68,7 @@
         }
 
         if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
-            appendPhase(new IterativeConditionalEliminationPhase());
+            appendPhase(new IterativeConditionalEliminationPhase(canonicalizer));
         }
 
         if (OptEliminatePartiallyRedundantGuards.getValue()) {
@@ -86,7 +85,7 @@
 
         appendPhase(new GuardLoweringPhase());
 
-        appendPhase(new LoweringPhase(LoweringType.AFTER_GUARDS));
+        appendPhase(new LoweringPhase(canonicalizer));
 
         appendPhase(new FrameStateAssignmentPhase());
 
--- a/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -27,6 +27,7 @@
 import org.junit.*;
 
 import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.internal.*;
 
 public class DebugHistogramTest {
 
@@ -34,8 +35,13 @@
     public void testEmptyHistogram() {
         DebugHistogram histogram = Debug.createHistogram("TestHistogram");
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-        histogram.print(new PrintStream(outputStream));
+
+        new DebugHistogramAsciiPrinter(new PrintStream(outputStream)).print(histogram);
         Assert.assertEquals("TestHistogram is empty.\n", outputStream.toString());
+
+        outputStream.reset();
+        new DebugHistogramRPrinter(new PrintStream(outputStream)).print(histogram);
+        Assert.assertEquals("", outputStream.toString());
     }
 
     @Test
@@ -44,19 +50,28 @@
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
         histogram.add(new Integer(1));
         histogram.add(new Integer(1));
-        histogram.print(new PrintStream(outputStream));
+        new DebugHistogramAsciiPrinter(new PrintStream(outputStream)).print(histogram);
         String[] lines = outputStream.toString().split("\n");
-        Assert.assertEquals(4, lines.length);
-        Assert.assertEquals("TestHistogram has 1 unique elements and 2 total elements:", lines[0]);
-        Assert.assertEquals(
-                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
-                        lines[1]);
-        Assert.assertEquals(
-                        "| 1                                                  | 2          | ==================================================================================================== |",
-                        lines[2]);
-        Assert.assertEquals(
-                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
-                        lines[3]);
+        // @formatter:off
+        String[] expected = {
+            "TestHistogram has 1 unique elements and 2 total elements:",
+            "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
+            "| 1                                                  | 2          | ==================================================================================================== |",
+            "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------"
+        };
+        // @formatter:on
+        Assert.assertArrayEquals(expected, lines);
+
+        outputStream.reset();
+        new DebugHistogramRPrinter(new PrintStream(outputStream)).print(histogram);
+        lines = outputStream.toString().split("\n");
+        // @formatter:off
+        expected = new String[] {
+            "TestHistogram <- c(2);",
+            "names(TestHistogram) <- c(\"1\");"
+        };
+        // @formatter:on
+        Assert.assertArrayEquals(expected, lines);
     }
 
     @Test
@@ -66,22 +81,29 @@
         histogram.add(new Integer(1));
         histogram.add(new Integer(2));
         histogram.add(new Integer(2));
-        histogram.print(new PrintStream(outputStream));
+        new DebugHistogramAsciiPrinter(new PrintStream(outputStream)).print(histogram);
         String[] lines = outputStream.toString().split("\n");
-        Assert.assertEquals(5, lines.length);
-        Assert.assertEquals("TestHistogram has 2 unique elements and 3 total elements:", lines[0]);
-        Assert.assertEquals(
-                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
-                        lines[1]);
-        Assert.assertEquals(
-                        "| 2                                                  | 2          | ==================================================================================================== |",
-                        lines[2]);
-        Assert.assertEquals(
-                        "| 1                                                  | 1          | ==================================================                                                   |",
-                        lines[3]);
-        Assert.assertEquals(
-                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
-                        lines[4]);
+        // @formatter:off
+        String[] expected = new String[] {
+            "TestHistogram has 2 unique elements and 3 total elements:",
+            "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
+            "| 2                                                  | 2          | ==================================================================================================== |",
+            "| 1                                                  | 1          | ==================================================                                                   |",
+            "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------"
+        };
+        // @formatter:on
+        Assert.assertArrayEquals(expected, lines);
+
+        outputStream.reset();
+        new DebugHistogramRPrinter(new PrintStream(outputStream)).print(histogram);
+        lines = outputStream.toString().split("\n");
+        // @formatter:off
+        expected = new String[] {
+            "TestHistogram <- c(2, 1);",
+            "names(TestHistogram) <- c(\"2\", \"1\");"
+        };
+        // @formatter:on
+        Assert.assertArrayEquals(expected, lines);
     }
 
     @Test
@@ -89,7 +111,7 @@
         DebugHistogram histogram = Debug.createHistogram("TestHistogram");
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
         histogram.add("MyCustomValue");
-        histogram.print(new PrintStream(outputStream), Integer.MAX_VALUE, 10, 10);
+        new DebugHistogramAsciiPrinter(new PrintStream(outputStream), Integer.MAX_VALUE, 10, 10).print(histogram);
         String[] lines = outputStream.toString().split("\n");
         Assert.assertEquals(4, lines.length);
         Assert.assertEquals("TestHistogram has 1 unique elements and 1 total elements:", lines[0]);
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Tue Sep 10 16:33:28 2013 -0700
@@ -330,7 +330,7 @@
 
     public static DebugMetric metric(String name) {
         if (ENABLED) {
-            return new MetricImpl(name);
+            return new MetricImpl(name, true);
         } else {
             return VOID_METRIC;
         }
@@ -342,6 +342,9 @@
         }
     }
 
+    /**
+     * Creates an object for counting value frequencies.
+     */
     public static DebugHistogram createHistogram(String name) {
         return new DebugHistogramImpl(name);
     }
@@ -402,11 +405,19 @@
 
         public void add(long value) {
         }
+
+        public void setConditional(boolean flag) {
+            throw new InternalError("Cannot make void metric conditional");
+        }
+
+        public boolean isConditional() {
+            return false;
+        }
     };
 
     public static DebugTimer timer(String name) {
         if (ENABLED) {
-            return new TimerImpl(name);
+            return new TimerImpl(name, true);
         } else {
             return VOID_TIMER;
         }
@@ -417,5 +428,13 @@
         public TimerCloseable start() {
             return TimerImpl.VOID_CLOSEABLE;
         }
+
+        public void setConditional(boolean flag) {
+            throw new InternalError("Cannot make void timer conditional");
+        }
+
+        public boolean isConditional() {
+            return false;
+        }
     };
 }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,15 +22,75 @@
  */
 package com.oracle.graal.debug;
 
-import java.io.*;
+import java.util.*;
 
+/**
+ * Facility for recording value frequencies.
+ */
 public interface DebugHistogram {
 
+    /**
+     * Gets the name specified when this objected was {@linkplain Debug#createHistogram(String)
+     * created}.
+     */
     String getName();
 
+    /**
+     * Increments the count for a given value.
+     */
     void add(Object value);
 
-    void print(PrintStream os);
+    /**
+     * A value and a frequency. The ordering imposed by {@link #compareTo(CountedValue)} places
+     * values with higher frequencies first.
+     */
+    public class CountedValue implements Comparable<CountedValue> {
+
+        private int count;
+        private final Object value;
+
+        public CountedValue(int count, Object value) {
+            this.count = count;
+            this.value = value;
+        }
+
+        public int compareTo(CountedValue o) {
+            if (count < o.count) {
+                return 1;
+            } else if (count > o.count) {
+                return -1;
+            }
+            return 0;
+        }
 
-    void print(PrintStream os, int limit, int nameSize, int barSize);
+        @Override
+        public String toString() {
+            return count + " -> " + value;
+        }
+
+        public void inc() {
+            count++;
+        }
+
+        public int getCount() {
+            return count;
+        }
+
+        public Object getValue() {
+            return value;
+        }
+    }
+
+    /**
+     * Gets a list of the counted values, sorted in descending order of frequency.
+     */
+    List<CountedValue> getValues();
+
+    /**
+     * Interface for a service that can render a visualization of a histogram.
+     */
+    public interface Printer {
+
+        void print(DebugHistogram histogram);
+    }
 }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugMetric.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugMetric.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,9 +22,32 @@
  */
 package com.oracle.graal.debug;
 
+/**
+ * A counter for some value of interest.
+ */
 public interface DebugMetric {
 
+    /**
+     * Adds 1 to this counter if metering is {@link Debug#isMeterEnabled() enabled} or this is an
+     * {@linkplain #isConditional() unconditional} metric.
+     */
     void increment();
 
+    /**
+     * Adds {@code value} to this counter if metering is {@link Debug#isMeterEnabled() enabled} or
+     * this is an {@linkplain #isConditional() unconditional} metric.
+     */
     void add(long value);
+
+    /**
+     * Sets a flag determining if this counter is only enabled if metering is
+     * {@link Debug#isMeterEnabled() enabled}.
+     */
+    void setConditional(boolean flag);
+
+    /**
+     * Determines if this counter is only enabled if metering is {@link Debug#isMeterEnabled()
+     * enabled}.
+     */
+    boolean isConditional();
 }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugTimer.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugTimer.java	Tue Sep 10 16:33:28 2013 -0700
@@ -24,7 +24,36 @@
 
 import com.oracle.graal.debug.internal.*;
 
+/**
+ * A timer for some activity of interest. A timer should be deployed using the try-with-resources
+ * pattern:
+ * 
+ * <pre>
+ * try (TimerCloseable a = timer.start()) {
+ *     // the code to time
+ * }
+ * </pre>
+ */
 public interface DebugTimer {
 
+    /**
+     * Starts this timer if timing is {@linkplain Debug#isTimeEnabled() enabled} or this is an
+     * {@linkplain #isConditional() unconditional} timer.
+     * 
+     * @return an object that must be closed once the activity has completed to add the elapsed time
+     *         since this call to the total for this timer
+     */
     TimerCloseable start();
+
+    /**
+     * Sets a flag determining if this timer is only enabled if metering is
+     * {@link Debug#isMeterEnabled() enabled}.
+     */
+    void setConditional(boolean flag);
+
+    /**
+     * Determines if this timer is only enabled if metering is {@link Debug#isMeterEnabled()
+     * enabled}.
+     */
+    boolean isConditional();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramAsciiPrinter.java	Tue Sep 10 16:33:28 2013 -0700
@@ -0,0 +1,101 @@
+/*
+ * 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.debug.internal;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.DebugHistogram.*;
+
+/**
+ * Renders a textual representation of a histogram to a given print stream.
+ */
+public class DebugHistogramAsciiPrinter implements Printer {
+
+    public static final int NumberSize = 10;
+    public static final int DefaultNameSize = 50;
+    public static final int DefaultBarSize = 100;
+
+    private PrintStream os;
+    private int limit;
+    private int nameSize;
+    private int barSize;
+
+    public DebugHistogramAsciiPrinter(PrintStream os) {
+        this(os, Integer.MAX_VALUE, DefaultNameSize, DefaultBarSize);
+    }
+
+    /**
+     * @param os where to print
+     * @param limit limits printing to the {@code limit} most frequent values
+     * @param nameSize the width of the value names column
+     * @param barSize the width of the value frequency column
+     */
+    public DebugHistogramAsciiPrinter(PrintStream os, int limit, int nameSize, int barSize) {
+        this.os = os;
+        this.limit = limit;
+        this.nameSize = nameSize;
+        this.barSize = barSize;
+    }
+
+    public void print(DebugHistogram histogram) {
+        List<CountedValue> list = histogram.getValues();
+        if (list.isEmpty()) {
+            os.printf("%s is empty.\n", histogram.getName());
+            return;
+        }
+
+        // Sum up the total number of elements.
+        int total = 0;
+        for (CountedValue cv : list) {
+            total += cv.getCount();
+        }
+
+        // Print header.
+        os.printf("%s has %d unique elements and %d total elements:\n", histogram.getName(), list.size(), total);
+
+        int max = list.get(0).getCount();
+        final int lineSize = nameSize + NumberSize + barSize + 10;
+        printLine(os, '-', lineSize);
+        String formatString = "| %-" + nameSize + "s | %-" + NumberSize + "d | %-" + barSize + "s |\n";
+        for (int i = 0; i < list.size() && i < limit; ++i) {
+            CountedValue cv = list.get(i);
+            int value = cv.getCount();
+            char[] bar = new char[(int) (((double) value / (double) max) * barSize)];
+            Arrays.fill(bar, '=');
+            String objectString = String.valueOf(cv.getValue());
+            if (objectString.length() > nameSize) {
+                objectString = objectString.substring(0, nameSize - 3) + "...";
+            }
+            os.printf(formatString, objectString, value, new String(bar));
+        }
+        printLine(os, '-', lineSize);
+    }
+
+    private static void printLine(PrintStream printStream, char c, int lineSize) {
+        char[] charArr = new char[lineSize];
+        Arrays.fill(charArr, c);
+        printStream.printf("%s\n", new String(charArr));
+    }
+}
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,28 +22,25 @@
  */
 package com.oracle.graal.debug.internal;
 
-import java.io.*;
 import java.util.*;
 
 import com.oracle.graal.debug.*;
 
 public class DebugHistogramImpl implements DebugHistogram {
 
-    public static final int NumberSize = 10;
-    public static final int DefaultNameSize = 50;
-    public static final int DefaultBarSize = 100;
     private final String name;
-    private HashMap<Object, Integer> map = new HashMap<>();
+    private HashMap<Object, CountedValue> map = new HashMap<>();
 
     public DebugHistogramImpl(String name) {
         this.name = name;
     }
 
     public void add(Object value) {
-        if (!map.containsKey(value)) {
-            map.put(value, 1);
+        CountedValue cv = map.get(value);
+        if (cv == null) {
+            map.put(value, new CountedValue(1, value));
         } else {
-            map.put(value, map.get(value) + 1);
+            cv.inc();
         }
     }
 
@@ -52,59 +49,9 @@
         return name;
     }
 
-    @Override
-    public void print(PrintStream os) {
-        print(os, Integer.MAX_VALUE, DefaultNameSize, DefaultBarSize);
-    }
-
-    public void print(PrintStream os, int limit, int nameSize, int barSize) {
-
-        List<Object> list = new ArrayList<>(map.keySet());
-        if (list.size() == 0) {
-            // No elements in the histogram.
-            os.printf("%s is empty.\n", name);
-            return;
-        }
-
-        // Sort from highest to smallest.
-        Collections.sort(list, new Comparator<Object>() {
-
-            @Override
-            public int compare(Object o1, Object o2) {
-                return map.get(o2) - map.get(o1);
-            }
-        });
-
-        // Sum up the total number of elements.
-        int total = 0;
-        for (Object o : list) {
-            total += map.get(o);
-        }
-
-        // Print header.
-        os.printf("%s has %d unique elements and %d total elements:\n", name, list.size(), total);
-
-        int max = map.get(list.get(0));
-        final int lineSize = nameSize + NumberSize + barSize + 10;
-        printLine(os, '-', lineSize);
-        String formatString = "| %-" + nameSize + "s | %-" + NumberSize + "d | %-" + barSize + "s |\n";
-        for (int i = 0; i < list.size() && i < limit; ++i) {
-            Object o = list.get(i);
-            int value = map.get(o);
-            char[] bar = new char[(int) (((double) value / (double) max) * barSize)];
-            Arrays.fill(bar, '=');
-            String objectString = o.toString();
-            if (objectString.length() > nameSize) {
-                objectString = objectString.substring(0, nameSize - 3) + "...";
-            }
-            os.printf(formatString, objectString, value, new String(bar));
-        }
-        printLine(os, '-', lineSize);
-    }
-
-    private static void printLine(PrintStream printStream, char c, int lineSize) {
-        char[] charArr = new char[lineSize];
-        Arrays.fill(charArr, c);
-        printStream.printf("%s\n", new String(charArr));
+    public List<CountedValue> getValues() {
+        ArrayList<CountedValue> res = new ArrayList<>(map.values());
+        Collections.sort(res);
+        return res;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramRPrinter.java	Tue Sep 10 16:33:28 2013 -0700
@@ -0,0 +1,81 @@
+/*
+ * 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.debug.internal;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.DebugHistogram.CountedValue;
+import com.oracle.graal.debug.DebugHistogram.Printer;
+
+/**
+ * Renders a histogram as an R script to a given print stream. The R script emitted for a histogram
+ * is a simple set of statements for defining a vector of named objects.
+ */
+public class DebugHistogramRPrinter implements Printer {
+
+    private PrintStream os;
+    private int limit;
+
+    public DebugHistogramRPrinter(PrintStream os) {
+        this(os, Integer.MAX_VALUE);
+    }
+
+    /**
+     * @param os where to print
+     * @param limit limits printing to the {@code limit} most frequent values
+     */
+    public DebugHistogramRPrinter(PrintStream os, int limit) {
+        this.os = os;
+        this.limit = limit;
+    }
+
+    public void print(DebugHistogram histogram) {
+        List<CountedValue> list = histogram.getValues();
+        if (list.isEmpty()) {
+            return;
+        }
+
+        String var = histogram.getName().replace('-', '.').replace(' ', '_');
+        os.print(var + " <- c(");
+        for (int i = 0; i < list.size() && i < limit; ++i) {
+            CountedValue cv = list.get(i);
+            if (i != 0) {
+                os.print(", ");
+            }
+            os.print(cv.getCount());
+        }
+        os.println(");");
+
+        os.print("names(" + var + ") <- c(");
+        for (int i = 0; i < list.size() && i < limit; ++i) {
+            CountedValue cv = list.get(i);
+            if (i != 0) {
+                os.print(", ");
+            }
+            os.print("\"" + cv.getValue() + "\"");
+        }
+        os.println(");");
+    }
+}
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MetricImpl.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MetricImpl.java	Tue Sep 10 16:33:28 2013 -0700
@@ -26,8 +26,11 @@
 
 public final class MetricImpl extends DebugValue implements DebugMetric {
 
-    public MetricImpl(String name) {
+    private boolean conditional;
+
+    public MetricImpl(String name, boolean conditional) {
         super(name);
+        this.conditional = conditional;
     }
 
     public void increment() {
@@ -35,7 +38,7 @@
     }
 
     public void add(long value) {
-        if (Debug.isMeterEnabled()) {
+        if (!conditional || Debug.isMeterEnabled()) {
             super.addToCurrentValue(value);
         }
     }
@@ -44,4 +47,12 @@
     public String toString(long value) {
         return Long.toString(value);
     }
+
+    public void setConditional(boolean flag) {
+        conditional = flag;
+    }
+
+    public boolean isConditional() {
+        return conditional;
+    }
 }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerCloseable.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerCloseable.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,6 +22,12 @@
  */
 package com.oracle.graal.debug.internal;
 
+import com.oracle.graal.debug.*;
+
+/**
+ * An object returned by {@link DebugTimer#start()} that when closed, stops the associated timer and
+ * adds the elapsed time since {@code start()} to the total for the timer.
+ */
 public interface TimerCloseable extends AutoCloseable {
 
     void close();
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerImpl.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerImpl.java	Tue Sep 10 16:33:28 2013 -0700
@@ -38,9 +38,19 @@
     };
 
     private ThreadLocal<Long> valueToSubstract = new ThreadLocal<>();
+    private boolean conditional;
 
-    public TimerImpl(String name) {
+    public TimerImpl(String name, boolean conditional) {
         super(name);
+        this.conditional = conditional;
+    }
+
+    public void setConditional(boolean flag) {
+        conditional = flag;
+    }
+
+    public boolean isConditional() {
+        return conditional;
     }
 
     @Override
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Sep 10 16:33:28 2013 -0700
@@ -25,7 +25,6 @@
 import java.util.*;
 
 import com.oracle.graal.graph.GraphEvent.NodeEvent;
-import com.oracle.graal.graph.Node.IterableNodeType;
 import com.oracle.graal.graph.Node.ValueNumberable;
 import com.oracle.graal.graph.iterators.*;
 
@@ -40,6 +39,16 @@
 
     private final ArrayList<Node> nodes;
 
+    /**
+     * Records the modification count for nodes. This is only used in assertions.
+     */
+    private int[] nodeModCounts;
+
+    /**
+     * Records the modification count for nodes' usage lists. This is only used in assertions.
+     */
+    private int[] nodeUsageModCounts;
+
     // these two arrays contain one entry for each NodeClass, indexed by NodeClass.iterableId.
     // they contain the first and last pointer to a linked list of all nodes with this type.
     private final ArrayList<Node> nodeCacheFirst;
@@ -87,6 +96,18 @@
         this(null);
     }
 
+    static final boolean MODIFICATION_COUNTS_ENABLED = assertionsEnabled();
+
+    /**
+     * Determines if assertions are enabled for the {@link Graph} class.
+     */
+    @SuppressWarnings("all")
+    private static boolean assertionsEnabled() {
+        boolean enabled = false;
+        assert enabled = true;
+        return enabled;
+    }
+
     /**
      * Creates an empty Graph with a given name.
      * 
@@ -97,6 +118,58 @@
         nodeCacheFirst = new ArrayList<>(NodeClass.cacheSize());
         nodeCacheLast = new ArrayList<>(NodeClass.cacheSize());
         this.name = name;
+        if (MODIFICATION_COUNTS_ENABLED) {
+            nodeModCounts = new int[nodes.size()];
+            nodeUsageModCounts = new int[nodes.size()];
+        }
+    }
+
+    int extractOriginalNodeId(Node node) {
+        int id = node.id;
+        if (id <= Node.DELETED_ID_START) {
+            id = Node.DELETED_ID_START - id;
+        }
+        return id;
+    }
+
+    int modCount(Node node) {
+        int id = extractOriginalNodeId(node);
+        if (id >= 0 && id < nodeModCounts.length) {
+            return nodeModCounts[id];
+        }
+        return 0;
+    }
+
+    void incModCount(Node node) {
+        int id = extractOriginalNodeId(node);
+        if (id >= 0) {
+            if (id >= nodeModCounts.length) {
+                nodeModCounts = Arrays.copyOf(nodeModCounts, id + 30);
+            }
+            nodeModCounts[id]++;
+        } else {
+            assert false;
+        }
+    }
+
+    int usageModCount(Node node) {
+        int id = extractOriginalNodeId(node);
+        if (id >= 0 && id < nodeUsageModCounts.length) {
+            return nodeUsageModCounts[id];
+        }
+        return 0;
+    }
+
+    void incUsageModCount(Node node) {
+        int id = extractOriginalNodeId(node);
+        if (id >= 0) {
+            if (id >= nodeUsageModCounts.length) {
+                nodeUsageModCounts = Arrays.copyOf(nodeUsageModCounts, id + 30);
+            }
+            nodeUsageModCounts[id]++;
+        } else {
+            assert false;
+        }
     }
 
     /**
@@ -340,7 +413,7 @@
     private static final Node PLACE_HOLDER = new Node() {
     };
 
-    private class TypedNodeIterator<T extends IterableNodeType> implements Iterator<T> {
+    private class TypedNodeIterator<T extends Node.IterableNodeType> implements Iterator<T> {
 
         private final int[] ids;
         private final Node[] current;
@@ -446,7 +519,7 @@
      * @param type the type of node to return
      * @return an {@link Iterable} providing all the matching nodes.
      */
-    public <T extends Node & IterableNodeType> NodeIterable<T> getNodes(final Class<T> type) {
+    public <T extends Node & Node.IterableNodeType> NodeIterable<T> getNodes(final Class<T> type) {
         final NodeClass nodeClass = NodeClass.get(type);
         return new AbstractNodeIterable<T>() {
 
@@ -463,7 +536,7 @@
      * @param type the type of node that is checked for occurrence
      * @return whether there is at least one such node
      */
-    public <T extends Node & IterableNodeType> boolean hasNode(final Class<T> type) {
+    public <T extends Node & Node.IterableNodeType> boolean hasNode(final Class<T> type) {
         return getNodes(type).iterator().hasNext();
     }
 
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,11 +22,14 @@
  */
 package com.oracle.graal.graph;
 
+import static com.oracle.graal.graph.Graph.*;
+
 import java.lang.annotation.*;
 import java.util.*;
 
 import com.oracle.graal.graph.Graph.NodeChangedListener;
-import com.oracle.graal.graph.NodeClass.*;
+import com.oracle.graal.graph.NodeClass.NodeClassIterator;
+import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.graph.iterators.*;
 
 /**
@@ -118,9 +121,18 @@
     // therefore points to the next Node of the same type.
     Node typeCacheNext;
 
-    private NodeUsagesList usages;
+    private static final int INLINE_USAGE_COUNT = 2;
+    private static final Node[] NO_NODES = {};
+
+    /**
+     * Head of usage list. The elements of the usage list in order are {@link #usage0},
+     * {@link #usage1} and {@link #extraUsages}. The first null entry terminates the list.
+     */
+    private Node usage0;
+    private Node usage1;
+    private Node[] extraUsages = NO_NODES;
+
     private Node predecessor;
-    private int modCount;
 
     public Node() {
         this.graph = null;
@@ -155,8 +167,211 @@
         return getNodeClass().getSuccessorIterable(this);
     }
 
+    class NodeUsageIterator implements Iterator<Node> {
+
+        private final int expectedModCount = usageModCount();
+        int index = -1;
+        Node current;
+
+        private void advance() {
+            assert index == -1 || current != null;
+            current = null;
+            index++;
+            if (index == 0) {
+                current = usage0;
+            } else if (index == 1) {
+                current = usage1;
+            } else {
+                if (index - INLINE_USAGE_COUNT < extraUsages.length) {
+                    current = extraUsages[index - INLINE_USAGE_COUNT];
+                }
+            }
+        }
+
+        public NodeUsageIterator() {
+            advance();
+        }
+
+        public boolean hasNext() {
+            assert expectedModCount == usageModCount();
+            return current != null;
+        }
+
+        public Node next() {
+            assert expectedModCount == usageModCount();
+            Node result = current;
+            if (result == null) {
+                throw new NoSuchElementException();
+            }
+            advance();
+            return result;
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    class NodeUsageIterable extends AbstractNodeIterable<Node> {
+
+        public NodeUsageIterator iterator() {
+            return new NodeUsageIterator();
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return usage0 == null;
+        }
+
+        @Override
+        public boolean isNotEmpty() {
+            return usage0 != null;
+        }
+
+        @Override
+        public int count() {
+            if (usage0 == null) {
+                return 0;
+            }
+            if (usage1 == null) {
+                return 1;
+            }
+            return 2 + indexOfLastNonNull(extraUsages) + 1;
+        }
+    }
+
+    /**
+     * Gets the list of nodes that use this node (e.g., as an input).
+     */
     public final NodeIterable<Node> usages() {
-        return usages;
+        return new NodeUsageIterable();
+    }
+
+    /**
+     * Finds the index of the last non-null entry in a node array. The search assumes that all
+     * non-null entries precede the first null entry in the array.
+     * 
+     * @param nodes the array to search
+     * @return the index of the last non-null entry in {@code nodes} if it exists, else -1
+     */
+    private static int indexOfLastNonNull(Node[] nodes) {
+        if (nodes.length == 0 || nodes[0] == null) {
+            return -1;
+        }
+        if (nodes[nodes.length - 1] != null) {
+            return nodes.length - 1;
+        }
+
+        // binary search
+        int low = 0;
+        int high = nodes.length - 1;
+        while (true) {
+            int mid = (low + high) >>> 1;
+            if (nodes[mid] == null) {
+                if (nodes[mid - 1] != null) {
+                    return mid - 1;
+                }
+                high = mid - 1;
+            } else {
+                if (mid == nodes.length - 1 || nodes[mid + 1] == null) {
+                    return mid;
+                }
+                low = mid + 1;
+            }
+        }
+    }
+
+    /**
+     * Adds a given node to this node's {@linkplain #usages() usages}.
+     * 
+     * @param node the node to add
+     */
+    private void addUsage(Node node) {
+        incUsageModCount();
+        if (usage0 == null) {
+            usage0 = node;
+        } else if (usage1 == null) {
+            usage1 = node;
+        } else {
+            int length = extraUsages.length;
+            if (length == 0) {
+                extraUsages = new Node[4];
+                extraUsages[0] = node;
+            } else {
+                int lastNonNull = indexOfLastNonNull(extraUsages);
+                if (lastNonNull == length - 1) {
+                    extraUsages = Arrays.copyOf(extraUsages, length * 2 + 1);
+                    extraUsages[length] = node;
+                } else if (lastNonNull == -1) {
+                    extraUsages[0] = node;
+                } else {
+                    extraUsages[lastNonNull + 1] = node;
+                }
+            }
+        }
+    }
+
+    /**
+     * Removes a given node from this node's {@linkplain #usages() usages}.
+     * 
+     * @param node the node to remove
+     * @return whether or not {@code usage} was in the usage list
+     */
+    private boolean removeUsage(Node node) {
+        // It is critical that this method maintains the invariant that
+        // the usage list has no null element preceding a non-null element
+        incUsageModCount();
+        if (usage0 == node) {
+            if (usage1 != null) {
+                int lastNonNull = indexOfLastNonNull(extraUsages);
+                if (lastNonNull >= 0) {
+                    usage0 = extraUsages[lastNonNull];
+                    extraUsages[lastNonNull] = null;
+                } else {
+                    // usage1 is the last element
+                    usage0 = usage1;
+                    usage1 = null;
+                }
+            } else {
+                // usage0 is the last element
+                usage0 = null;
+            }
+            return true;
+        }
+        if (usage1 == node) {
+            int lastNonNull = indexOfLastNonNull(extraUsages);
+            if (lastNonNull >= 0) {
+                usage1 = extraUsages[lastNonNull];
+                extraUsages[lastNonNull] = null;
+            } else {
+                // usage1 is the last element
+                usage1 = null;
+            }
+            return true;
+        }
+        int lastNonNull = indexOfLastNonNull(extraUsages);
+        if (lastNonNull >= 0) {
+            for (int i = 0; i <= lastNonNull; ++i) {
+                Node n = extraUsages[i];
+                if (n == node) {
+                    if (i < lastNonNull) {
+                        extraUsages[i] = extraUsages[lastNonNull];
+                        extraUsages[lastNonNull] = null;
+                    } else {
+                        extraUsages[i] = null;
+                    }
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private void clearUsages() {
+        incUsageModCount();
+        usage0 = null;
+        usage1 = null;
+        extraUsages = NO_NODES;
     }
 
     public final Node predecessor() {
@@ -164,11 +379,29 @@
     }
 
     final int modCount() {
-        return modCount;
+        if (MODIFICATION_COUNTS_ENABLED && graph != null) {
+            return graph.modCount(this);
+        }
+        return 0;
     }
 
     final void incModCount() {
-        modCount++;
+        if (MODIFICATION_COUNTS_ENABLED && graph != null) {
+            graph.incModCount(this);
+        }
+    }
+
+    final int usageModCount() {
+        if (MODIFICATION_COUNTS_ENABLED && graph != null) {
+            return graph.usageModCount(this);
+        }
+        return 0;
+    }
+
+    final void incUsageModCount() {
+        if (MODIFICATION_COUNTS_ENABLED && graph != null) {
+            graph.incUsageModCount(this);
+        }
     }
 
     public boolean isDeleted() {
@@ -184,7 +417,6 @@
      * newInput: removes this node from oldInput's usages and adds this node to newInput's usages.
      */
     protected void updateUsages(Node oldInput, Node newInput) {
-        assert assertTrue(usages != null, "usages == null while adding %s to %s", newInput, this);
         if (oldInput != newInput) {
             if (oldInput != null) {
                 boolean result = removeThisFromUsages(oldInput);
@@ -195,8 +427,7 @@
                 if (inputChanged != null) {
                     inputChanged.nodeChanged(this);
                 }
-                assert newInput.usages != null : "not yet added? " + newInput;
-                newInput.usages.add(this);
+                newInput.addUsage(this);
             } else if (oldInput != null && oldInput.usages().isEmpty()) {
                 NodeChangedListener nodeChangedListener = graph.usagesDroppedZero;
                 if (nodeChangedListener != null) {
@@ -212,7 +443,6 @@
      * this node to newSuccessor's predecessors.
      */
     protected void updatePredecessor(Node oldSuccessor, Node newSuccessor) {
-        assert assertTrue(usages != null, "usages == null while adding %s to %s", newSuccessor, this);
         if (oldSuccessor != newSuccessor) {
             if (oldSuccessor != null) {
                 assert assertTrue(oldSuccessor.predecessor == this, "wrong predecessor in old successor (%s): %s", oldSuccessor, oldSuccessor.predecessor);
@@ -229,7 +459,6 @@
         assert assertTrue(id == INITIAL_ID, "unexpected id: %d", id);
         this.graph = newGraph;
         newGraph.register(this);
-        usages = new NodeUsagesList();
         for (Node input : inputs()) {
             updateUsages(null, input);
         }
@@ -252,7 +481,7 @@
 
     public void replaceAtUsages(Node other) {
         assert checkReplaceWith(other);
-        for (Node usage : usages) {
+        for (Node usage : usages()) {
             boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other);
             assert assertTrue(result, "not found in inputs, usage: %s", usage);
             if (other != null) {
@@ -260,10 +489,10 @@
                 if (inputChanged != null) {
                     inputChanged.nodeChanged(usage);
                 }
-                other.usages.add(usage);
+                other.addUsage(usage);
             }
         }
-        usages.clear();
+        clearUsages();
     }
 
     public void replaceAtPredecessor(Node other) {
@@ -313,11 +542,7 @@
     }
 
     private boolean removeThisFromUsages(Node n) {
-        if (n.usages.remove(this)) {
-            return true;
-        } else {
-            return false;
-        }
+        return n.removeUsage(this);
     }
 
     public void clearSuccessors() {
@@ -331,7 +556,7 @@
     }
 
     private boolean checkDeletion() {
-        assertTrue(usages.isEmpty(), "cannot delete node %s because of usages: %s", this, usages);
+        assertTrue(usages().isEmpty(), "cannot delete node %s because of usages: %s", this, usages());
         assertTrue(predecessor == null, "cannot delete node %s because of predecessor: %s", this, predecessor);
         return true;
     }
@@ -354,7 +579,7 @@
         NodeClass clazz = getNodeClass();
         clazz.copyInputs(this, newNode);
         for (Node input : inputs()) {
-            input.usages.add(newNode);
+            input.addUsage(newNode);
         }
         return newNode;
     }
@@ -372,9 +597,10 @@
         newNode.typeCacheNext = null;
         newNode.id = INITIAL_ID;
         into.register(newNode);
-        newNode.usages = new NodeUsagesList();
+        newNode.usage0 = null;
+        newNode.usage1 = null;
+        newNode.extraUsages = NO_NODES;
         newNode.predecessor = null;
-        newNode.modCount = 0;
         return newNode;
     }
 
@@ -575,10 +801,10 @@
         }
 
         if (precision > 0) {
-            if (this.usages.count() > 0) {
+            if (!usages().isEmpty()) {
                 formatter.format(" usages={");
                 int z = 0;
-                for (Node usage : this.usages) {
+                for (Node usage : usages()) {
                     if (z != 0) {
                         formatter.format(", ");
                     }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.graph;
 
+import static com.oracle.graal.graph.Graph.*;
+
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.Map.Entry;
@@ -29,7 +31,6 @@
 
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.Node.Input;
-import com.oracle.graal.graph.Node.IterableNodeType;
 import com.oracle.graal.graph.Node.Successor;
 import com.oracle.graal.graph.Node.Verbosity;
 
@@ -38,7 +39,7 @@
  * <ul>
  * <li>The offsets of fields annotated with {@link Input} and {@link Successor} as well as methods
  * for iterating over such fields.</li>
- * <li>The identifier for an {@link IterableNodeType} class.</li>
+ * <li>The identifier for an {@link Node.IterableNodeType} class.</li>
  * </ul>
  */
 public final class NodeClass extends FieldIntrospection {
@@ -432,7 +433,7 @@
          */
         private NodeClassIterator(Node node, long[] offsets, int directCount) {
             this.node = node;
-            this.modCount = node.modCount();
+            this.modCount = MODIFICATION_COUNTS_ENABLED ? node.modCount() : 0;
             this.offsets = offsets;
             this.directCount = directCount;
             index = NOT_ITERABLE;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java	Tue Sep 10 16:33:28 2013 -0700
@@ -39,13 +39,13 @@
 
     public NodeInputList(Node self, T[] elements) {
         super(elements);
-        assert self.usages() == null;
+        assert self.usages().isEmpty();
         this.self = self;
     }
 
     public NodeInputList(Node self, List<? extends T> elements) {
         super(elements);
-        assert self.usages() == null;
+        assert self.usages().isEmpty();
         this.self = self;
     }
 
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorList.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorList.java	Tue Sep 10 16:33:28 2013 -0700
@@ -37,7 +37,7 @@
 
     public NodeSuccessorList(Node self, T[] elements) {
         super(elements);
-        assert self.usages() == null;
+        assert self.usages().isEmpty();
         this.self = self;
     }
 
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsagesList.java	Tue Sep 10 16:32:27 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +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.graph;
-
-import java.util.*;
-
-import com.oracle.graal.graph.iterators.*;
-
-public final class NodeUsagesList extends AbstractNodeIterable<Node> {
-
-    protected static final Node[] EMPTY_NODE_ARRAY = new Node[0];
-
-    protected Node[] nodes = EMPTY_NODE_ARRAY;
-    private int size;
-    private int modCount;
-
-    NodeUsagesList() {
-        this.size = 0;
-        this.nodes = EMPTY_NODE_ARRAY;
-    }
-
-    NodeUsagesList(Node[] nodes) {
-        this.size = nodes.length;
-        this.nodes = nodes;
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return size == 0;
-    }
-
-    @Override
-    public boolean isNotEmpty() {
-        return size > 0;
-    }
-
-    @Override
-    public int count() {
-        return size;
-    }
-
-    @Override
-    public Iterator<Node> iterator() {
-        return new Iterator<Node>() {
-
-            private final int expectedModCount = NodeUsagesList.this.modCount;
-            private int index = 0;
-
-            @Override
-            public boolean hasNext() {
-                assert expectedModCount == NodeUsagesList.this.modCount;
-                return index < NodeUsagesList.this.size;
-            }
-
-            @Override
-            public Node next() {
-                assert expectedModCount == NodeUsagesList.this.modCount;
-                return NodeUsagesList.this.nodes[index++];
-            }
-
-            @Override
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-        };
-    }
-
-    @Override
-    public boolean contains(Node other) {
-        for (int i = 0; i < size; i++) {
-            if (nodes[i] == other) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public List<Node> snapshot() {
-        return Arrays.asList(Arrays.copyOf(NodeUsagesList.this.nodes, NodeUsagesList.this.size));
-    }
-
-    private void incModCount() {
-        modCount++;
-    }
-
-    boolean add(Node node) {
-        incModCount();
-        if (size == nodes.length) {
-            nodes = Arrays.copyOf(nodes, nodes.length * 2 + 1);
-        }
-        nodes[size++] = node;
-        return true;
-    }
-
-    void copyAndClear(NodeUsagesList other) {
-        incModCount();
-        other.incModCount();
-        nodes = other.nodes;
-        size = other.size;
-        nodes = EMPTY_NODE_ARRAY;
-        size = 0;
-    }
-
-    void clear() {
-        incModCount();
-        nodes = EMPTY_NODE_ARRAY;
-        size = 0;
-    }
-
-    boolean remove(Node node) {
-        int i = 0;
-        incModCount();
-        while (i < size && nodes[i] != node) {
-            i++;
-        }
-        if (i < size) {
-            i++;
-            while (i < size) {
-                nodes[i - 1] = nodes[i];
-                i++;
-            }
-            nodes[--size] = null;
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder str = new StringBuilder();
-        str.append('[');
-        for (int i = 0; i < size; i++) {
-            if (i > 0) {
-                str.append(", ");
-            }
-            str.append(nodes[i]);
-        }
-        str.append(']');
-        return str.toString();
-    }
-}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Tue Sep 10 16:33:28 2013 -0700
@@ -45,7 +45,7 @@
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
-import com.oracle.graal.lir.StandardOp.ParametersOp;
+import com.oracle.graal.lir.StandardOp.LabelOp;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
@@ -214,7 +214,7 @@
         };
         for (Block block : lir.codeEmittingOrder()) {
             for (LIRInstruction op : lir.lir(block)) {
-                if (op instanceof ParametersOp) {
+                if (op instanceof LabelOp) {
                     // Don't consider this as a definition
                 } else {
                     op.forEachTemp(defProc);
@@ -244,10 +244,10 @@
             AMD64Address src = new AMD64Address(receiver, config.hubOffset);
 
             AMD64HotSpotLIRGenerator gen = (AMD64HotSpotLIRGenerator) lirGen;
-            HotSpotRuntime hr = ((HotSpotRuntime) gen.getRuntime());
-            if (hr.config.useCompressedKlassPointers) {
+            AMD64HotSpotRuntime hr = ((AMD64HotSpotRuntime) gen.getRuntime());
+            if (hr.useCompressedKlassPointers()) {
                 Register register = r10;
-                AMD64Move.decodeKlassPointer(asm, register, hr.heapBaseRegister(), src, hr.config.narrowKlassBase, hr.config.narrowKlassShift, hr.config.logKlassAlignment);
+                AMD64HotSpotMove.decodeKlassPointer(asm, register, hr.heapBaseRegister(), src, config.narrowKlassBase, config.narrowKlassShift, config.logKlassAlignment);
                 asm.cmpq(inlineCacheKlass, register);
             } else {
                 asm.cmpq(inlineCacheKlass, src);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Sep 10 16:33:28 2013 -0700
@@ -38,20 +38,20 @@
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.CompareAndSwapCompressedOp;
+import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.LoadCompressedPointer;
+import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.StoreCompressedConstantOp;
+import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.StoreCompressedPointer;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.ParametersOp;
 import com.oracle.graal.lir.StandardOp.PlaceholderOp;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
-import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapCompressedOp;
 import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
-import com.oracle.graal.lir.amd64.AMD64Move.LoadCompressedPointer;
 import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
-import com.oracle.graal.lir.amd64.AMD64Move.StoreCompressedPointer;
 import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StoreOp;
 import com.oracle.graal.nodes.*;
@@ -161,9 +161,8 @@
             }
         }
         params[params.length - 1] = rbpParam;
-        ParametersOp paramsOp = new ParametersOp(params);
 
-        append(paramsOp);
+        emitIncomingValues(params);
 
         saveRbp = new SaveRbp(new PlaceholderOp(currentBlock, lir.lir(currentBlock).size()));
         append(saveRbp.placeholder);
@@ -427,12 +426,12 @@
          * algorithms may differ.
          */
         if (isCompressCandidate(access)) {
-            if (runtime().config.useCompressedOops && kind == Kind.Object) {
-                append(new LoadCompressedPointer(kind, result, runtime().heapBaseRegister().asValue(), loadAddress, access != null ? state(access) : null, runtime().config.narrowOopBase,
-                                runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
-            } else if (runtime().config.useCompressedKlassPointers && kind == Kind.Long) {
-                append(new LoadCompressedPointer(kind, result, runtime().heapBaseRegister().asValue(), loadAddress, access != null ? state(access) : null, runtime().config.narrowKlassBase,
-                                runtime().config.narrowKlassShift, runtime().config.logKlassAlignment));
+            if (runtime().useCompressedOops() && kind == Kind.Object) {
+                append(new LoadCompressedPointer(kind, result, runtime().heapBaseRegister().asValue(), loadAddress, access != null ? state(access) : null, getNarrowOopBase(), getNarrowOopShift(),
+                                getLogMinObjectAlignment()));
+            } else if (runtime().useCompressedKlassPointers() && kind == Kind.Long) {
+                append(new LoadCompressedPointer(kind, result, runtime().heapBaseRegister().asValue(), loadAddress, access != null ? state(access) : null, getNarrowKlassBase(), getNarrowKlassShift(),
+                                getLogKlassAlignment()));
             } else {
                 append(new LoadOp(kind, result, loadAddress, access != null ? state(access) : null));
             }
@@ -449,29 +448,29 @@
         if (isConstant(inputVal)) {
             Constant c = asConstant(inputVal);
             if (canStoreConstant(c)) {
-                if (inputVal.getKind() == Kind.Object) {
-                    append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedOops && isCompressCandidate(access)));
-                } else if (inputVal.getKind() == Kind.Long) {
-                    append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedKlassPointers && isCompressCandidate(access)));
+                if (inputVal.getKind() == Kind.Object && runtime().useCompressedOops() && isCompressCandidate(access)) {
+                    append(new StoreCompressedConstantOp(kind, storeAddress, c, state));
+                } else if (inputVal.getKind() == Kind.Long && runtime().useCompressedKlassPointers() && isCompressCandidate(access)) {
+                    append(new StoreCompressedConstantOp(kind, storeAddress, c, state));
                 } else {
-                    append(new StoreConstantOp(kind, storeAddress, c, state, false));
+                    append(new StoreConstantOp(kind, storeAddress, c, state));
                 }
                 return;
             }
         }
         Variable input = load(inputVal);
         if (isCompressCandidate(access)) {
-            if (runtime().config.useCompressedOops && kind == Kind.Object) {
+            if (runtime().useCompressedOops() && kind == Kind.Object) {
                 if (input.getKind() == Kind.Object) {
                     Variable scratch = newVariable(Kind.Long);
-                    append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
+                    append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment()));
                 } else {
                     // the input oop is already compressed
                     append(new StoreOp(input.getKind(), storeAddress, input, state));
                 }
-            } else if (runtime().config.useCompressedKlassPointers && kind == Kind.Long) {
+            } else if (runtime().useCompressedKlassPointers() && kind == Kind.Long) {
                 Variable scratch = newVariable(Kind.Long);
-                append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, runtime().config.narrowKlassBase, runtime().config.narrowKlassShift, runtime().config.logKlassAlignment));
+                append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, getNarrowKlassBase(), getNarrowKlassShift(), getLogKlassAlignment()));
             } else {
                 append(new StoreOp(kind, storeAddress, input, state));
             }
@@ -480,6 +479,30 @@
         }
     }
 
+    private int getLogMinObjectAlignment() {
+        return runtime().config.logMinObjAlignment;
+    }
+
+    private int getNarrowOopShift() {
+        return runtime().config.narrowOopShift;
+    }
+
+    private long getNarrowOopBase() {
+        return runtime().config.narrowOopBase;
+    }
+
+    private int getLogKlassAlignment() {
+        return runtime().config.logKlassAlignment;
+    }
+
+    private int getNarrowKlassShift() {
+        return runtime().config.narrowKlassShift;
+    }
+
+    private long getNarrowKlassBase() {
+        return runtime().config.narrowKlassBase;
+    }
+
     @Override
     public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) {
         Kind kind = node.getNewValue().kind();
@@ -489,9 +512,9 @@
         AMD64AddressValue addressValue = asAddressValue(address);
         RegisterValue raxRes = AMD64.rax.asValue(kind);
         emitMove(raxRes, expected);
-        if (runtime().config.useCompressedOops && node.isCompressible()) {
+        if (runtime().useCompressedOops() && node.isCompressible()) {
             Variable scratch = newVariable(Kind.Long);
-            append(new CompareAndSwapCompressedOp(raxRes, addressValue, raxRes, newValue, scratch, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
+            append(new CompareAndSwapCompressedOp(raxRes, addressValue, raxRes, newValue, scratch, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment()));
         } else {
             append(new CompareAndSwapOp(raxRes, addressValue, raxRes, newValue));
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Tue Sep 10 16:33:28 2013 -0700
@@ -0,0 +1,250 @@
+/*
+ * 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.hotspot.amd64;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.amd64.*;
+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.amd64.AMD64Assembler.ConditionFlag;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
+import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp;
+import com.oracle.graal.lir.asm.*;
+
+public class AMD64HotSpotMove {
+
+    public static class StoreCompressedConstantOp extends StoreConstantOp {
+
+        public StoreCompressedConstantOp(Kind kind, AMD64AddressValue address, Constant input, LIRFrameState state) {
+            super(kind, address, input, state);
+        }
+
+        @Override
+        public void emitMemAccess(AMD64MacroAssembler masm) {
+            if (kind == Kind.Long) {
+                if (NumUtil.isInt(input.asLong())) {
+                    masm.movl(address.toAddress(), (int) input.asLong());
+                } else {
+                    throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
+                }
+            } else if (kind == Kind.Object) {
+                if (input.isNull()) {
+                    masm.movl(address.toAddress(), 0);
+                } else {
+                    throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
+                }
+            } else {
+                throw GraalInternalError.shouldNotReachHere("Attempt to store compressed constant of wrong type.");
+            }
+        }
+    }
+
+    public static class LoadCompressedPointer extends LoadOp {
+
+        private long base;
+        private int shift;
+        private int alignment;
+        @Alive({REG}) protected AllocatableValue heapBaseRegister;
+
+        public LoadCompressedPointer(Kind kind, AllocatableValue result, AllocatableValue heapBaseRegister, AMD64AddressValue address, LIRFrameState state, long base, int shift, int alignment) {
+            super(kind, result, address, state);
+            this.base = base;
+            this.shift = shift;
+            this.alignment = alignment;
+            this.heapBaseRegister = heapBaseRegister;
+            assert kind == Kind.Object || kind == Kind.Long;
+        }
+
+        @Override
+        public void emitMemAccess(AMD64MacroAssembler masm) {
+            Register resRegister = asRegister(result);
+            masm.movl(resRegister, address.toAddress());
+            if (kind == Kind.Object) {
+                decodePointer(masm, resRegister, asRegister(heapBaseRegister), base, shift, alignment);
+            } else {
+                decodeKlassPointer(masm, resRegister, asRegister(heapBaseRegister), base, shift, alignment);
+            }
+        }
+    }
+
+    public static class StoreCompressedPointer extends AMD64LIRInstruction {
+
+        protected final Kind kind;
+        private long base;
+        private int shift;
+        private int alignment;
+        @Temp({REG}) private AllocatableValue scratch;
+        @Alive({REG}) protected AllocatableValue input;
+        @Alive({COMPOSITE}) protected AMD64AddressValue address;
+        @State protected LIRFrameState state;
+
+        public StoreCompressedPointer(Kind kind, AMD64AddressValue address, AllocatableValue input, AllocatableValue scratch, LIRFrameState state, long base, int shift, int alignment) {
+            this.base = base;
+            this.shift = shift;
+            this.alignment = alignment;
+            this.scratch = scratch;
+            this.kind = kind;
+            this.address = address;
+            this.state = state;
+            this.input = input;
+            assert kind == Kind.Object || kind == Kind.Long;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            Register heapBase = ((HotSpotRuntime) tasm.runtime).heapBaseRegister();
+            masm.movq(asRegister(scratch), asRegister(input));
+            if (kind == Kind.Object) {
+                encodePointer(masm, asRegister(scratch), heapBase, base, shift, alignment);
+            } else {
+                encodeKlassPointer(masm, asRegister(scratch), heapBase, base, shift, alignment);
+            }
+            if (state != null) {
+                tasm.recordImplicitException(masm.codeBuffer.position(), state);
+            }
+            masm.movl(address.toAddress(), asRegister(scratch));
+        }
+    }
+
+    @Opcode("CAS")
+    public static class CompareAndSwapCompressedOp extends AMD64LIRInstruction {
+
+        @Def protected AllocatableValue result;
+        @Alive({COMPOSITE}) protected AMD64AddressValue address;
+        @Alive protected AllocatableValue cmpValue;
+        @Alive protected AllocatableValue newValue;
+        @Temp({REG}) protected AllocatableValue scratch;
+
+        private long base;
+        private int shift;
+        private int alignment;
+
+        public CompareAndSwapCompressedOp(AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue, AllocatableValue scratch, long base, int shift,
+                        int alignment) {
+            this.base = base;
+            this.shift = shift;
+            this.alignment = alignment;
+            this.scratch = scratch;
+            this.result = result;
+            this.address = address;
+            this.cmpValue = cmpValue;
+            this.newValue = newValue;
+            assert cmpValue.getKind() == Kind.Object;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            compareAndSwapCompressed(tasm, masm, result, address, cmpValue, newValue, scratch, base, shift, alignment);
+        }
+    }
+
+    protected static void compareAndSwapCompressed(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue,
+                    AllocatableValue newValue, AllocatableValue scratch, long base, int shift, int alignment) {
+        assert AMD64.rax.equals(asRegister(cmpValue)) && AMD64.rax.equals(asRegister(result));
+        final Register scratchRegister = asRegister(scratch);
+        final Register cmpRegister = asRegister(cmpValue);
+        final Register newRegister = asRegister(newValue);
+        Register heapBase = ((HotSpotRuntime) tasm.runtime).heapBaseRegister();
+        encodePointer(masm, cmpRegister, heapBase, base, shift, alignment);
+        masm.movq(scratchRegister, newRegister);
+        encodePointer(masm, scratchRegister, heapBase, base, shift, alignment);
+        if (tasm.target.isMP) {
+            masm.lock();
+        }
+        masm.cmpxchgl(scratchRegister, address.toAddress());
+    }
+
+    private static void encodePointer(AMD64MacroAssembler masm, Register scratchRegister, Register heapBaseRegister, long base, int shift, int alignment) {
+        // If the base is zero, the uncompressed address has to be shifted right
+        // in order to be compressed.
+        if (base == 0) {
+            if (shift != 0) {
+                assert alignment == shift : "Encode algorithm is wrong";
+                masm.shrq(scratchRegister, alignment);
+            }
+        } else {
+            // Otherwise the heap base, which resides always in register 12, is subtracted
+            // followed by right shift.
+            masm.testq(scratchRegister, scratchRegister);
+            // If the stored reference is null, move the heap to scratch
+            // register and then calculate the compressed oop value.
+            masm.cmovq(ConditionFlag.Equal, scratchRegister, heapBaseRegister);
+            masm.subq(scratchRegister, heapBaseRegister);
+            masm.shrq(scratchRegister, alignment);
+        }
+    }
+
+    private static void decodePointer(AMD64MacroAssembler masm, Register resRegister, Register heapBaseRegister, long base, int shift, int alignment) {
+        // If the base is zero, the compressed address has to be shifted left
+        // in order to be uncompressed.
+        if (base == 0) {
+            if (shift != 0) {
+                assert alignment == shift : "Decode algorithm is wrong";
+                masm.shlq(resRegister, alignment);
+            }
+        } else {
+            Label done = new Label();
+            masm.shlq(resRegister, alignment);
+            masm.jccb(ConditionFlag.Equal, done);
+            // Otherwise the heap base is added to the shifted address.
+            masm.addq(resRegister, heapBaseRegister);
+            masm.bind(done);
+        }
+    }
+
+    private static void encodeKlassPointer(AMD64MacroAssembler masm, Register scratchRegister, Register heapBaseRegister, long base, int shift, int alignment) {
+        if (base != 0) {
+            masm.subq(scratchRegister, heapBaseRegister);
+        }
+        if (shift != 0) {
+            assert alignment == shift : "Encode algorithm is wrong";
+            masm.shrq(scratchRegister, alignment);
+        }
+    }
+
+    private static void decodeKlassPointer(AMD64MacroAssembler masm, Register resRegister, Register heapBaseRegister, long base, int shift, int alignment) {
+        if (shift != 0) {
+            assert alignment == shift : "Decode algorithm is wrong";
+            masm.shlq(resRegister, alignment);
+            if (base != 0) {
+                masm.addq(resRegister, heapBaseRegister);
+            }
+        } else {
+            assert base == 0 : "Sanity";
+        }
+    }
+
+    public static void decodeKlassPointer(AMD64MacroAssembler masm, Register register, Register heapBaseRegister, AMD64Address address, long narrowKlassBase, int narrowKlassShift,
+                    int logKlassAlignment) {
+        masm.movl(register, address);
+        decodeKlassPointer(masm, register, heapBaseRegister, narrowKlassBase, narrowKlassShift, logKlassAlignment);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -39,7 +39,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -249,10 +248,10 @@
                 StructuredGraph graph = parse(snippet);
                 HighTierContext highContext = new HighTierContext(runtime(), new Assumptions(false), replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
                 MidTierContext midContext = new MidTierContext(runtime(), new Assumptions(false), replacements, runtime().getTarget(), OptimisticOptimizations.ALL);
-                new InliningPhase(new InliningPhase.InlineEverythingPolicy()).apply(graph, highContext);
-                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, highContext);
+                new InliningPhase(new InliningPhase.InlineEverythingPolicy(), new CanonicalizerPhase(true)).apply(graph, highContext);
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, highContext);
                 new GuardLoweringPhase().apply(graph, midContext);
-                new LoweringPhase(LoweringType.AFTER_GUARDS).apply(graph, midContext);
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, midContext);
                 new WriteBarrierAdditionPhase().apply(graph);
                 Debug.dump(graph, "After Write Barrier Addition");
 
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -36,7 +36,6 @@
 import com.oracle.graal.hotspot.phases.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.graph.*;
@@ -633,14 +632,14 @@
             public AssertionError call() {
                 final StructuredGraph graph = parse(snippet);
                 HighTierContext highTierContext = new HighTierContext(runtime(), new Assumptions(false), replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-                new InliningPhase().apply(graph, highTierContext);
+                new InliningPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext);
 
                 MidTierContext midTierContext = new MidTierContext(runtime(), new Assumptions(false), replacements, runtime().getTarget(), OptimisticOptimizations.ALL);
 
-                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, highTierContext);
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext);
                 new GuardLoweringPhase().apply(graph, midTierContext);
                 new SafepointInsertionPhase().apply(graph);
-                new LoweringPhase(LoweringType.AFTER_GUARDS).apply(graph, highTierContext);
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext);
 
                 new WriteBarrierAdditionPhase().apply(graph);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Tue Sep 10 16:33:28 2013 -0700
@@ -113,6 +113,8 @@
      */
     public static final DebugTimer CompilationTime = Debug.timer("CompilationTime");
 
+    public static final DebugTimer CodeInstallationTime = Debug.timer("CodeInstallation");
+
     public void runCompilation() {
         /*
          * no code must be outside this try/finally because it could happen otherwise that
@@ -164,7 +166,9 @@
                 }
             }
 
-            installMethod(result);
+            try (TimerCloseable b = CodeInstallationTime.start()) {
+                installMethod(result);
+            }
             stats.finish(method);
         } catch (BailoutException bailout) {
             Debug.metric("Bailouts").increment();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot;
 
-import static com.oracle.graal.compiler.GraalDebugConfig.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import java.io.*;
@@ -52,7 +51,7 @@
     @Override
     public void run() {
         GraalDebugConfig hotspotDebugConfig = null;
-        if (DebugEnabled.getValue()) {
+        if (Debug.isEnabled()) {
             PrintStream log = graalRuntime().getVMToCompiler().log();
             DebugEnvironment.initialize(log);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Tue Sep 10 16:33:28 2013 -0700
@@ -23,6 +23,7 @@
 
 package com.oracle.graal.hotspot;
 
+import static com.oracle.graal.compiler.GraalDebugConfig.*;
 import static java.nio.file.Files.*;
 
 import java.io.*;
@@ -30,6 +31,7 @@
 import java.nio.file.*;
 import java.util.*;
 
+import com.oracle.graal.debug.*;
 import com.oracle.graal.hotspot.logging.*;
 import com.oracle.graal.options.*;
 
@@ -174,6 +176,18 @@
     }
 
     /**
+     * Called from VM code once all Graal command line options have been processed by
+     * {@link #setOption(String)}.
+     * 
+     * @param ciTime the value of the CITime HotSpot VM option
+     */
+    public static void finalizeOptions(boolean ciTime) {
+        if (areDebugScopePatternsEnabled() || ciTime) {
+            Debug.enable();
+        }
+    }
+
+    /**
      * Wraps some given text to one or more lines of a given maximum width.
      * 
      * @param text text to wrap
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Tue Sep 10 16:33:28 2013 -0700
@@ -38,7 +38,7 @@
 
     private static final long serialVersionUID = -4744897993263044184L;
 
-    private final HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean();
+    private static final HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean();
 
     HotSpotVMConfig(CompilerToVM c2vm) {
         c2vm.initializeConfiguration(this);
@@ -52,9 +52,9 @@
      * @return value of option
      * @throws IllegalArgumentException if option doesn't exist
      */
-    private int getVMOptionInt(String name) {
+    public static int getVMOptionInt(String name) {
         String value = diagnostic.getVMOption(name).getValue();
-        return new Integer(value).intValue();
+        return Integer.valueOf(value).intValue();
     }
 
     /**
@@ -64,7 +64,7 @@
      * @param defaultValue default value if option is not exists (e.g. development options)
      * @return value of option or defaultValue if option doesn't exist
      */
-    private int getVMOption(String name, int defaultValue) {
+    public static int getVMOption(String name, int defaultValue) {
         try {
             return getVMOptionInt(name);
         } catch (IllegalArgumentException e) {
@@ -79,9 +79,9 @@
      * @return value of option
      * @throws IllegalArgumentException if option doesn't exist
      */
-    private boolean getVMOption(String name) {
+    public static boolean getVMOption(String name) {
         String value = diagnostic.getVMOption(name).getValue();
-        return new Boolean(value).booleanValue();
+        return Boolean.valueOf(value).booleanValue();
     }
 
     /**
@@ -91,7 +91,7 @@
      * @param defaultValue default value if option is not exists (e.g. development options)
      * @return value of option or defaultValue if option doesn't exist
      */
-    private boolean getVMOption(String name, boolean defaultValue) {
+    public static boolean getVMOption(String name, boolean defaultValue) {
         try {
             return getVMOption(name);
         } catch (IllegalArgumentException e) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Tue Sep 10 16:33:28 2013 -0700
@@ -226,4 +226,6 @@
     void reprofile(long metaspaceMethod);
 
     void invalidateInstalledCode(HotSpotInstalledCode hotspotInstalledCode);
+
+    boolean isTypeLinked(HotSpotResolvedObjectType hotSpotResolvedObjectType);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Tue Sep 10 16:33:28 2013 -0700
@@ -102,6 +102,8 @@
     @Override
     public native boolean isTypeInitialized(HotSpotResolvedObjectType klass);
 
+    public native boolean isTypeLinked(HotSpotResolvedObjectType hotSpotResolvedObjectType);
+
     @Override
     public native boolean hasFinalizableSubclass(HotSpotResolvedObjectType klass);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Tue Sep 10 16:33:28 2013 -0700
@@ -29,6 +29,7 @@
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.java.GraphBuilderPhase.*;
 import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.phases.common.InliningUtil.*;
 
 import java.io.*;
 import java.lang.reflect.*;
@@ -51,7 +52,6 @@
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
-import com.oracle.graal.phases.common.*;
 import com.oracle.graal.printer.*;
 import com.oracle.graal.replacements.*;
 
@@ -105,8 +105,6 @@
 
     private PrintStream log = System.out;
 
-    private boolean quietMeterAndTime;
-
     private long compilerStartTime;
 
     public VMToCompilerImpl(HotSpotGraalRuntime compiler) {
@@ -165,13 +163,12 @@
         }
 
         if (config.ciTime) {
-            quietMeterAndTime = (Meter.getValue() == null && Time.getValue() == null);
-            DebugEnabled.setValue(true);
-            Meter.setValue("");
-            Time.setValue("");
+            BytecodesParsed.setConditional(false);
+            InlinedBytecodes.setConditional(false);
+            CompilationTime.setConditional(false);
         }
 
-        if (DebugEnabled.getValue()) {
+        if (Debug.isEnabled()) {
             DebugEnvironment.initialize(log);
 
             String summary = DebugValueSummary.getValue();
@@ -374,7 +371,7 @@
         CompilationStatistics.clear(phase);
         if (graalRuntime.getConfig().ciTime) {
             parsedBytecodesPerSecond = MetricRateInPhase.snapshot(phase, parsedBytecodesPerSecond, BytecodesParsed, CompilationTime, TimeUnit.SECONDS);
-            inlinedBytecodesPerSecond = MetricRateInPhase.snapshot(phase, inlinedBytecodesPerSecond, InliningUtil.InlinedBytecodes, CompilationTime, TimeUnit.SECONDS);
+            inlinedBytecodesPerSecond = MetricRateInPhase.snapshot(phase, inlinedBytecodesPerSecond, InlinedBytecodes, CompilationTime, TimeUnit.SECONDS);
         }
     }
 
@@ -476,7 +473,7 @@
             CompilationTask.withinEnqueue.set(Boolean.FALSE);
         }
 
-        if (Debug.isEnabled() && !quietMeterAndTime) {
+        if (Debug.isEnabled() && areDebugScopePatternsEnabled()) {
             List<DebugValueMap> topLevelMaps = DebugValueMap.getTopLevelMaps();
             List<DebugValue> debugValues = KeyRegistry.getDebugValues();
             if (debugValues.size() > 0) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Tue Sep 10 16:33:28 2013 -0700
@@ -167,7 +167,7 @@
         return true;
     }
 
-    private static final String SystemClassName = MetaUtil.toInternalName(System.class.getName());
+    private static final String SystemClassName = "Ljava/lang/System;";
 
     @Override
     public Constant readConstantValue(Constant receiver) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Tue Sep 10 16:33:28 2013 -0700
@@ -138,7 +138,7 @@
         if (codeSize == 0) {
             return null;
         }
-        if (code == null) {
+        if (code == null && graalRuntime().getCompilerToVM().isTypeLinked(holder)) {
             code = graalRuntime().getCompilerToVM().initializeBytecode(metaspaceMethod, new byte[codeSize]);
             assert code.length == codeSize : "expected: " + codeSize + ", actual: " + code.length;
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Tue Sep 10 16:33:28 2013 -0700
@@ -83,6 +83,7 @@
     private ResolvedJavaType[] interfaces;
     private ConstantPool constantPool;
     private boolean isInitialized;
+    private boolean isLinked;
     private ResolvedJavaType arrayOfType;
 
     /**
@@ -292,9 +293,18 @@
     }
 
     @Override
+    public boolean isLinked() {
+        if (!isLinked) {
+            isLinked = graalRuntime().getCompilerToVM().isTypeLinked(this);
+        }
+        return isLinked;
+    }
+
+    @Override
     public void initialize() {
         if (!isInitialized) {
             graalRuntime().getCompilerToVM().initializeType(this);
+            assert graalRuntime().getCompilerToVM().isTypeInitialized(this);
         }
         isInitialized = true;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Tue Sep 10 16:33:28 2013 -0700
@@ -112,6 +112,10 @@
         return true;
     }
 
+    public boolean isLinked() {
+        return true;
+    }
+
     @Override
     public boolean isInstance(Constant obj) {
         return false;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Tue Sep 10 16:33:28 2013 -0700
@@ -85,7 +85,6 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.tiers.*;
@@ -313,31 +312,15 @@
         linkForeignCall(r, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
         linkForeignCall(r, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
 
-        if (IntrinsifyObjectMethods.getValue()) {
-            r.registerSubstitutions(ObjectSubstitutions.class);
-        }
-        if (IntrinsifySystemMethods.getValue()) {
-            r.registerSubstitutions(SystemSubstitutions.class);
-        }
-        if (IntrinsifyThreadMethods.getValue()) {
-            r.registerSubstitutions(ThreadSubstitutions.class);
-        }
-        if (IntrinsifyUnsafeMethods.getValue()) {
-            r.registerSubstitutions(UnsafeSubstitutions.class);
-        }
-        if (IntrinsifyClassMethods.getValue()) {
-            r.registerSubstitutions(ClassSubstitutions.class);
-        }
-        if (IntrinsifyAESMethods.getValue()) {
-            r.registerSubstitutions(AESCryptSubstitutions.class);
-            r.registerSubstitutions(CipherBlockChainingSubstitutions.class);
-        }
-        if (IntrinsifyCRC32Methods.getValue()) {
-            r.registerSubstitutions(CRC32Substitutions.class);
-        }
-        if (IntrinsifyReflectionMethods.getValue()) {
-            r.registerSubstitutions(ReflectionSubstitutions.class);
-        }
+        r.registerSubstitutions(ObjectSubstitutions.class);
+        r.registerSubstitutions(SystemSubstitutions.class);
+        r.registerSubstitutions(ThreadSubstitutions.class);
+        r.registerSubstitutions(UnsafeSubstitutions.class);
+        r.registerSubstitutions(ClassSubstitutions.class);
+        r.registerSubstitutions(AESCryptSubstitutions.class);
+        r.registerSubstitutions(CipherBlockChainingSubstitutions.class);
+        r.registerSubstitutions(CRC32Substitutions.class);
+        r.registerSubstitutions(ReflectionSubstitutions.class);
 
         checkcastDynamicSnippets = new CheckCastDynamicSnippets.Templates(this, r, graalRuntime.getTarget());
         instanceofSnippets = new InstanceOfSnippets.Templates(this, r, graalRuntime.getTarget());
@@ -361,6 +344,12 @@
     public abstract Register threadRegister();
 
     /**
+     * Returns the register used by the runtime for maintaining the heap base address for compressed
+     * pointers.
+     */
+    public abstract Register heapBaseRegister();
+
+    /**
      * Gets the stack pointer register.
      */
     public abstract Register stackPointerRegister();
@@ -494,6 +483,14 @@
         return Array.getLength(array.asObject());
     }
 
+    public boolean useCompressedOops() {
+        return config.useCompressedOops;
+    }
+
+    public boolean useCompressedKlassPointers() {
+        return config.useCompressedKlassPointers;
+    }
+
     @Override
     public void lower(Node n, LoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) n.graph();
@@ -639,11 +636,11 @@
             graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
 
         } else if (n instanceof UnsafeLoadNode) {
-            if (tool.getLoweringType().ordinal() > LoweringType.BEFORE_GUARDS.ordinal()) {
+            if (graph.getGuardsPhase().ordinal() > StructuredGraph.GuardsPhase.FLOATING_GUARDS.ordinal()) {
                 UnsafeLoadNode load = (UnsafeLoadNode) n;
                 assert load.kind() != Kind.Illegal;
                 boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object);
-                if (addReadBarrier(load, tool)) {
+                if (addReadBarrier(load)) {
                     unsafeLoadSnippets.lower(load, tool);
                 } else {
                     IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, 1);
@@ -678,14 +675,8 @@
             StoreHubNode storeHub = (StoreHubNode) n;
             WriteNode hub = createWriteHub(graph, wordKind, storeHub.getObject(), storeHub.getValue());
             graph.replaceFixed(storeHub, hub);
-        } else if (n instanceof FixedGuardNode) {
-            FixedGuardNode node = (FixedGuardNode) n;
-            GuardingNode guard = tool.createGuard(node.condition(), node.getReason(), node.getAction(), node.isNegated());
-            ValueAnchorNode newAnchor = graph.add(new ValueAnchorNode(guard.asNode()));
-            node.replaceAtUsages(guard.asNode());
-            graph.replaceFixedWithFixed(node, newAnchor);
         } else if (n instanceof CommitAllocationNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsPhase.FIXED_DEOPTS) {
                 CommitAllocationNode commit = (CommitAllocationNode) n;
 
                 ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()];
@@ -761,7 +752,7 @@
                 graph.removeFixed(commit);
             }
         } else if (n instanceof OSRStartNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsPhase.FIXED_DEOPTS) {
                 OSRStartNode osrStart = (OSRStartNode) n;
                 StartNode newStart = graph.add(new StartNode());
                 LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind())));
@@ -790,31 +781,31 @@
         } else if (n instanceof CheckCastDynamicNode) {
             checkcastDynamicSnippets.lower((CheckCastDynamicNode) n);
         } else if (n instanceof InstanceOfNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsPhase.FIXED_DEOPTS) {
                 instanceofSnippets.lower((InstanceOfNode) n, tool);
             }
         } else if (n instanceof InstanceOfDynamicNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsPhase.FIXED_DEOPTS) {
                 instanceofSnippets.lower((InstanceOfDynamicNode) n, tool);
             }
         } else if (n instanceof NewInstanceNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_FSA) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsPhase.AFTER_FSA) {
                 newObjectSnippets.lower((NewInstanceNode) n);
             }
         } else if (n instanceof NewArrayNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_FSA) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsPhase.AFTER_FSA) {
                 newObjectSnippets.lower((NewArrayNode) n);
             }
         } else if (n instanceof DynamicNewArrayNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_FSA) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsPhase.AFTER_FSA) {
                 newObjectSnippets.lower((DynamicNewArrayNode) n);
             }
         } else if (n instanceof MonitorEnterNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsPhase.FIXED_DEOPTS) {
                 monitorSnippets.lower((MonitorEnterNode) n, tool);
             }
         } else if (n instanceof MonitorExitNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsPhase.FIXED_DEOPTS) {
                 monitorSnippets.lower((MonitorExitNode) n, tool);
             }
         } else if (n instanceof G1PreWriteBarrier) {
@@ -832,7 +823,7 @@
         } else if (n instanceof G1ArrayRangePostWriteBarrier) {
             writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, tool);
         } else if (n instanceof NewMultiArrayNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_FSA) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsPhase.AFTER_FSA) {
                 newObjectSnippets.lower((NewMultiArrayNode) n);
             }
         } else if (n instanceof LoadExceptionObjectNode) {
@@ -852,8 +843,8 @@
         }
     }
 
-    private static boolean addReadBarrier(UnsafeLoadNode load, LoweringTool tool) {
-        if (useG1GC() && tool.getLoweringType() == LoweringType.AFTER_GUARDS && load.object().kind() == Kind.Object && load.accessKind() == Kind.Object &&
+    private static boolean addReadBarrier(UnsafeLoadNode load) {
+        if (useG1GC() && load.graph().getGuardsPhase() == StructuredGraph.GuardsPhase.FIXED_DEOPTS && load.object().kind() == Kind.Object && load.accessKind() == Kind.Object &&
                         !ObjectStamp.isObjectAlwaysNull(load.object())) {
             ResolvedJavaType type = ObjectStamp.typeOrNull(load.object());
             if (type != null && !type.isArray()) {
@@ -879,13 +870,13 @@
     private FloatingReadNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object, GuardingNode guard) {
         LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph);
         assert !object.isConstant() || object.asConstant().isNull();
-        return graph.add(new FloatingReadNode(object, location, null, StampFactory.forKind(wordKind()), guard, BarrierType.NONE, config.useCompressedKlassPointers));
+        return graph.add(new FloatingReadNode(object, location, null, StampFactory.forKind(wordKind()), guard, BarrierType.NONE, useCompressedKlassPointers()));
     }
 
     private WriteNode createWriteHub(StructuredGraph graph, Kind wordKind, ValueNode object, ValueNode value) {
         LocationNode location = ConstantLocationNode.create(ANY_LOCATION, wordKind, config.hubOffset, graph);
         assert !object.isConstant() || object.asConstant().isNull();
-        return graph.add(new WriteNode(object, value, location, BarrierType.NONE, config.useCompressedKlassPointers));
+        return graph.add(new WriteNode(object, value, location, BarrierType.NONE, useCompressedKlassPointers()));
     }
 
     private static BarrierType getFieldLoadBarrierType(HotSpotResolvedJavaField loadField) {
@@ -943,7 +934,7 @@
     }
 
     public int getScalingFactor(Kind kind) {
-        if (config.useCompressedOops && kind == Kind.Object) {
+        if (useCompressedOops() && kind == Kind.Object) {
             return this.graalRuntime.getTarget().arch.getSizeInBytes(Kind.Int);
         } else {
             return this.graalRuntime.getTarget().arch.getSizeInBytes(kind);
@@ -1150,7 +1141,7 @@
             case Int:
                 return Constant.forInt(base == null ? unsafe.getInt(displacement) : unsafe.getInt(base, displacement));
             case Long:
-                if (displacement == config().hubOffset && this.getGraalRuntime().getRuntime().config.useCompressedKlassPointers) {
+                if (displacement == config().hubOffset && useCompressedKlassPointers()) {
                     if (base == null) {
                         throw new GraalInternalError("Base of object must not be null");
                     } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -44,7 +44,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         byte[] formatBytes = string.getBytes();
         long cstring = unsafe.allocateMemory(formatBytes.length + 1);
         for (int i = 0; i < formatBytes.length; i++) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/VerifyHotSpotOptionsPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/VerifyHotSpotOptionsPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -57,31 +57,41 @@
             for (OptionDescriptor desc : opts) {
                 if (HotSpotOptions.isHotSpotOption(desc)) {
                     HotSpotResolvedObjectType holder = (HotSpotResolvedObjectType) runtime.lookupJavaType(desc.getDeclaringClass());
-                    if (!checked.contains(holder)) {
-                        checked.add(holder);
-                        for (ResolvedJavaMethod method : holder.getMethods()) {
-                            if (method.isClassInitializer()) {
-                                StructuredGraph graph = new StructuredGraph(method);
-                                new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
-                                new VerifyHotSpotOptionsPhase(holder, runtime).apply(graph);
-                            }
-                        }
-                    }
+                    checkType(holder, desc, runtime, checked);
                 }
             }
         }
         return true;
     }
 
+    private static void checkType(HotSpotResolvedObjectType type, OptionDescriptor option, HotSpotRuntime runtime, Set<HotSpotResolvedObjectType> checked) {
+        if (!checked.contains(type)) {
+            checked.add(type);
+            HotSpotResolvedObjectType superType = type.getSupertype();
+            if (superType != null && !MetaUtil.isJavaLangObject(superType)) {
+                checkType(superType, option, runtime, checked);
+            }
+            for (ResolvedJavaMethod method : type.getMethods()) {
+                if (method.isClassInitializer()) {
+                    StructuredGraph graph = new StructuredGraph(method);
+                    new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
+                    new VerifyHotSpotOptionsPhase(type, runtime, option).apply(graph);
+                }
+            }
+        }
+    }
+
     private final HotSpotRuntime runtime;
     private final ResolvedJavaType declaringClass;
     private final ResolvedJavaType optionValueType;
     private final Set<ResolvedJavaType> boxingTypes;
+    private final OptionDescriptor option;
 
-    public VerifyHotSpotOptionsPhase(ResolvedJavaType declaringClass, HotSpotRuntime runtime) {
+    public VerifyHotSpotOptionsPhase(ResolvedJavaType declaringClass, HotSpotRuntime runtime, OptionDescriptor option) {
         this.runtime = runtime;
         this.declaringClass = declaringClass;
         this.optionValueType = runtime.lookupJavaType(OptionValue.class);
+        this.option = option;
         this.boxingTypes = new HashSet<>();
         for (Class c : new Class[]{Boolean.class, Byte.class, Short.class, Character.class, Integer.class, Float.class, Long.class, Double.class}) {
             this.boxingTypes.add(runtime.lookupJavaType(c));
@@ -136,7 +146,9 @@
 
     private void error(Node node, String message) {
         String loc = GraphUtil.approxSourceLocation(node);
-        throw new GraalInternalError(String.format("HotSpot option declarer %s contains code pattern implying action other than initialization of an option:%n    %s%n    %s",
+        throw new GraalInternalError(String.format("The " + option.getName() + " option is declared in " + option.getDeclaringClass() +
+                        " whose class hierarchy contains a class initializer (in %s) with a code pattern at or near %s implying an action other than initialization of an option:%n%n    %s%n%n" +
+                        "The recommended solution is to move " + option.getName() + " into a separate class (e.g., " + option.getDeclaringClass().getName() + ".Options).%n",
                         toJavaName(declaringClass), loc, message));
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.GraalCompiler.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.Node.IterableNodeType;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -37,7 +37,7 @@
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.nodes.*;
 
-public class ArrayCopyNode extends MacroNode implements Virtualizable, IterableNodeType, Lowerable {
+public class ArrayCopyNode extends MacroNode implements Virtualizable, Node.IterableNodeType, Lowerable {
 
     public ArrayCopyNode(Invoke invoke) {
         super(invoke);
@@ -87,13 +87,13 @@
         // additions, etc.
         PhaseContext context = new PhaseContext(tool.getRuntime(), tool.assumptions(), tool.getReplacements());
         new CanonicalizerPhase(true).apply(snippetGraph, context);
-        new LoopFullUnrollPhase(true).apply(snippetGraph, context);
+        new LoopFullUnrollPhase(new CanonicalizerPhase(true)).apply(snippetGraph, context);
         new CanonicalizerPhase(true).apply(snippetGraph, context);
     }
 
     @Override
     protected StructuredGraph getSnippetGraph(LoweringTool tool) {
-        if (!IntrinsifyArrayCopy.getValue()) {
+        if (!shouldIntrinsify(getTargetMethod())) {
             return null;
         }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import static com.oracle.graal.phases.GraalOptions.*;
-
 import java.lang.invoke.*;
 
 import com.oracle.graal.api.code.*;
@@ -37,11 +35,9 @@
 
     @Override
     public void registerReplacements(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
-        if (IntrinsifyCallSiteTarget.getValue()) {
-            replacements.registerSubstitutions(ConstantCallSiteSubstitutions.class);
-            replacements.registerSubstitutions(MutableCallSiteSubstitutions.class);
-            replacements.registerSubstitutions(VolatileCallSiteSubstitutions.class);
-        }
+        replacements.registerSubstitutions(ConstantCallSiteSubstitutions.class);
+        replacements.registerSubstitutions(MutableCallSiteSubstitutions.class);
+        replacements.registerSubstitutions(VolatileCallSiteSubstitutions.class);
     }
 
     @ClassSubstitution(ConstantCallSite.class)
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -66,7 +66,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         ConstantNode target = getConstantCallTarget(tool.getRuntime(), tool.assumptions());
 
         if (target != null) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Tue Sep 10 16:33:28 2013 -0700
@@ -167,7 +167,7 @@
      */
     public static boolean clearPendingException(Word thread) {
         boolean result = thread.readObject(threadPendingExceptionOffset(), PENDING_EXCEPTION_LOCATION) != null;
-        thread.writeObject(threadPendingExceptionOffset(), null);
+        thread.writeObject(threadPendingExceptionOffset(), null, PENDING_EXCEPTION_LOCATION);
         return result;
     }
 
@@ -178,7 +178,7 @@
      */
     public static Object getAndClearObjectResult(Word thread) {
         Object result = thread.readObject(objectResultOffset(), OBJECT_RESULT_LOCATION);
-        thread.writeObject(objectResultOffset(), null);
+        thread.writeObject(objectResultOffset(), null, OBJECT_RESULT_LOCATION);
         return result;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.GraalCompiler.*;
 
 import java.lang.reflect.*;
 
@@ -52,7 +52,7 @@
 
     @Override
     protected StructuredGraph getSnippetGraph(LoweringTool tool) {
-        if (!IntrinsifyObjectClone.getValue()) {
+        if (!shouldIntrinsify(getTargetMethod())) {
             return null;
         }
 
@@ -121,7 +121,7 @@
             ResolvedJavaType type = getConcreteType(obj.stamp(), tool.getAssumptions());
             if (isCloneableType(type, tool.getMetaAccessProvider())) {
                 if (!type.isArray()) {
-                    VirtualInstanceNode newVirtual = new VirtualInstanceNode(type);
+                    VirtualInstanceNode newVirtual = new VirtualInstanceNode(type, true);
                     ResolvedJavaField[] fields = newVirtual.getFields();
 
                     ValueNode[] state = new ValueNode[fields.length];
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.GraalCompiler.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
@@ -47,7 +47,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         ConstantNode callerClassNode = getCallerClassNode(tool.getRuntime());
 
         if (callerClassNode != null) {
@@ -65,7 +65,7 @@
      * @return ConstantNode of the caller class, or null
      */
     private ConstantNode getCallerClassNode(MetaAccessProvider runtime) {
-        if (!IntrinsifyReflectionMethods.getValue()) {
+        if (!shouldIntrinsify(getTargetMethod())) {
             return null;
         }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -92,8 +92,8 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.AFTER_FSA) {
+    public void lower(LoweringTool tool) {
+        if (graph().getGuardsPhase() == StructuredGraph.GuardsPhase.AFTER_FSA) {
             UnsafeArrayCopySnippets.Templates templates = tool.getReplacements().getSnippetTemplateCache(UnsafeArrayCopySnippets.Templates.class);
             templates.lower(this);
         }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -242,7 +242,7 @@
 
         // remove dead FrameStates
         for (Node n : currentGraph.getNodes(FrameState.class)) {
-            if (n.usages().count() == 0 && n.predecessor() == null) {
+            if (n.usages().isEmpty() && n.predecessor() == null) {
                 n.safeDelete();
             }
         }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Tue Sep 10 16:33:28 2013 -0700
@@ -32,7 +32,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
@@ -117,34 +116,6 @@
         }
     }
 
-    public static class LoadCompressedPointer extends LoadOp {
-
-        private long base;
-        private int shift;
-        private int alignment;
-        @Alive({REG}) protected AllocatableValue heapBaseRegister;
-
-        public LoadCompressedPointer(Kind kind, AllocatableValue result, AllocatableValue heapBaseRegister, AMD64AddressValue address, LIRFrameState state, long base, int shift, int alignment) {
-            super(kind, result, address, state);
-            this.base = base;
-            this.shift = shift;
-            this.alignment = alignment;
-            this.heapBaseRegister = heapBaseRegister;
-            assert kind == Kind.Object || kind == Kind.Long;
-        }
-
-        @Override
-        public void emitMemAccess(AMD64MacroAssembler masm) {
-            Register resRegister = asRegister(result);
-            masm.movl(resRegister, address.toAddress());
-            if (kind == Kind.Object) {
-                decodePointer(masm, resRegister, asRegister(heapBaseRegister), base, shift, alignment);
-            } else {
-                decodeKlassPointer(masm, resRegister, asRegister(heapBaseRegister), base, shift, alignment);
-            }
-        }
-    }
-
     public static class LoadOp extends MemOp {
 
         @Def({REG}) protected AllocatableValue result;
@@ -188,44 +159,6 @@
         }
     }
 
-    public static class StoreCompressedPointer extends AMD64LIRInstruction {
-
-        protected final Kind kind;
-        private long base;
-        private int shift;
-        private int alignment;
-        @Temp({REG}) private AllocatableValue scratch;
-        @Alive({REG}) protected AllocatableValue input;
-        @Alive({COMPOSITE}) protected AMD64AddressValue address;
-        @State protected LIRFrameState state;
-
-        public StoreCompressedPointer(Kind kind, AMD64AddressValue address, AllocatableValue input, AllocatableValue scratch, LIRFrameState state, long base, int shift, int alignment) {
-            this.base = base;
-            this.shift = shift;
-            this.alignment = alignment;
-            this.scratch = scratch;
-            this.kind = kind;
-            this.address = address;
-            this.state = state;
-            this.input = input;
-            assert kind == Kind.Object || kind == Kind.Long;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            masm.movq(asRegister(scratch), asRegister(input));
-            if (kind == Kind.Object) {
-                encodePointer(masm, asRegister(scratch), tasm.runtime.heapBaseRegister(), base, shift, alignment);
-            } else {
-                encodeKlassPointer(masm, asRegister(scratch), tasm.runtime.heapBaseRegister(), base, shift, alignment);
-            }
-            if (state != null) {
-                tasm.recordImplicitException(masm.codeBuffer.position(), state);
-            }
-            masm.movl(address.toAddress(), asRegister(scratch));
-        }
-    }
-
     public static class StoreOp extends MemOp {
 
         @Use({REG}) protected AllocatableValue input;
@@ -271,12 +204,10 @@
     public static class StoreConstantOp extends MemOp {
 
         protected final Constant input;
-        private final boolean compressible;
 
-        public StoreConstantOp(Kind kind, AMD64AddressValue address, Constant input, LIRFrameState state, boolean compressible) {
+        public StoreConstantOp(Kind kind, AMD64AddressValue address, Constant input, LIRFrameState state) {
             super(kind, address, state);
             this.input = input;
-            this.compressible = compressible;
         }
 
         @Override
@@ -295,11 +226,7 @@
                     break;
                 case Long:
                     if (NumUtil.isInt(input.asLong())) {
-                        if (compressible) {
-                            masm.movl(address.toAddress(), (int) input.asLong());
-                        } else {
-                            masm.movslq(address.toAddress(), (int) input.asLong());
-                        }
+                        masm.movslq(address.toAddress(), (int) input.asLong());
                     } else {
                         throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
                     }
@@ -311,11 +238,7 @@
                     throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
                 case Object:
                     if (input.isNull()) {
-                        if (compressible) {
-                            masm.movl(address.toAddress(), 0);
-                        } else {
-                            masm.movptr(address.toAddress(), 0);
-                        }
+                        masm.movptr(address.toAddress(), 0);
                     } else {
                         throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
                     }
@@ -410,38 +333,6 @@
         }
     }
 
-    @Opcode("CAS")
-    public static class CompareAndSwapCompressedOp extends AMD64LIRInstruction {
-
-        @Def protected AllocatableValue result;
-        @Alive({COMPOSITE}) protected AMD64AddressValue address;
-        @Alive protected AllocatableValue cmpValue;
-        @Alive protected AllocatableValue newValue;
-        @Temp({REG}) protected AllocatableValue scratch;
-
-        private long base;
-        private int shift;
-        private int alignment;
-
-        public CompareAndSwapCompressedOp(AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue, AllocatableValue scratch, long base, int shift,
-                        int alignment) {
-            this.base = base;
-            this.shift = shift;
-            this.alignment = alignment;
-            this.scratch = scratch;
-            this.result = result;
-            this.address = address;
-            this.cmpValue = cmpValue;
-            this.newValue = newValue;
-            assert cmpValue.getKind() == Kind.Object;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            compareAndSwapCompressed(tasm, masm, result, address, cmpValue, newValue, scratch, base, shift, alignment);
-        }
-    }
-
     public static void move(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Value input) {
         if (isRegister(input)) {
             if (isRegister(result)) {
@@ -650,85 +541,4 @@
                 throw GraalInternalError.shouldNotReachHere();
         }
     }
-
-    protected static void compareAndSwapCompressed(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue,
-                    AllocatableValue newValue, AllocatableValue scratch, long base, int shift, int alignment) {
-        assert AMD64.rax.equals(asRegister(cmpValue)) && AMD64.rax.equals(asRegister(result));
-        final Register scratchRegister = asRegister(scratch);
-        final Register cmpRegister = asRegister(cmpValue);
-        final Register newRegister = asRegister(newValue);
-        encodePointer(masm, cmpRegister, tasm.runtime.heapBaseRegister(), base, shift, alignment);
-        masm.movq(scratchRegister, newRegister);
-        encodePointer(masm, scratchRegister, tasm.runtime.heapBaseRegister(), base, shift, alignment);
-        if (tasm.target.isMP) {
-            masm.lock();
-        }
-        masm.cmpxchgl(scratchRegister, address.toAddress());
-    }
-
-    private static void encodePointer(AMD64MacroAssembler masm, Register scratchRegister, Register heapBaseRegister, long base, int shift, int alignment) {
-        // If the base is zero, the uncompressed address has to be shifted right
-        // in order to be compressed.
-        if (base == 0) {
-            if (shift != 0) {
-                assert alignment == shift : "Encode algorithm is wrong";
-                masm.shrq(scratchRegister, alignment);
-            }
-        } else {
-            // Otherwise the heap base, which resides always in register 12, is subtracted
-            // followed by right shift.
-            masm.testq(scratchRegister, scratchRegister);
-            // If the stored reference is null, move the heap to scratch
-            // register and then calculate the compressed oop value.
-            masm.cmovq(ConditionFlag.Equal, scratchRegister, heapBaseRegister);
-            masm.subq(scratchRegister, heapBaseRegister);
-            masm.shrq(scratchRegister, alignment);
-        }
-    }
-
-    private static void decodePointer(AMD64MacroAssembler masm, Register resRegister, Register heapBaseRegister, long base, int shift, int alignment) {
-        // If the base is zero, the compressed address has to be shifted left
-        // in order to be uncompressed.
-        if (base == 0) {
-            if (shift != 0) {
-                assert alignment == shift : "Decode algorithm is wrong";
-                masm.shlq(resRegister, alignment);
-            }
-        } else {
-            Label done = new Label();
-            masm.shlq(resRegister, alignment);
-            masm.jccb(ConditionFlag.Equal, done);
-            // Otherwise the heap base is added to the shifted address.
-            masm.addq(resRegister, heapBaseRegister);
-            masm.bind(done);
-        }
-    }
-
-    private static void encodeKlassPointer(AMD64MacroAssembler masm, Register scratchRegister, Register heapBaseRegister, long base, int shift, int alignment) {
-        if (base != 0) {
-            masm.subq(scratchRegister, heapBaseRegister);
-        }
-        if (shift != 0) {
-            assert alignment == shift : "Encode algorithm is wrong";
-            masm.shrq(scratchRegister, alignment);
-        }
-    }
-
-    private static void decodeKlassPointer(AMD64MacroAssembler masm, Register resRegister, Register heapBaseRegister, long base, int shift, int alignment) {
-        if (shift != 0) {
-            assert alignment == shift : "Decode algorithm is wrong";
-            masm.shlq(resRegister, alignment);
-            if (base != 0) {
-                masm.addq(resRegister, heapBaseRegister);
-            }
-        } else {
-            assert base == 0 : "Sanity";
-        }
-    }
-
-    public static void decodeKlassPointer(AMD64MacroAssembler masm, Register register, Register heapBaseRegister, AMD64Address address, long narrowKlassBase, int narrowKlassShift,
-                    int logKlassAlignment) {
-        masm.movl(register, address);
-        decodeKlassPointer(masm, register, heapBaseRegister, narrowKlassBase, narrowKlassShift, logKlassAlignment);
-    }
 }
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Tue Sep 10 16:33:28 2013 -0700
@@ -316,7 +316,7 @@
                     masm.cvt_f32_f64(asFloatReg(dst), asDoubleReg(src));
                     break;
                 case LSHL:
-                    masm.shl_s64(asLongReg(dst), asLongReg(dst), asIntReg(src));
+                    masm.shl_b64(asLongReg(dst), asLongReg(dst), asIntReg(src));
                     break;
                 case LSHR:
                     masm.shr_s64(asLongReg(dst), asLongReg(dst), asIntReg(src));
@@ -360,19 +360,19 @@
             switch (opcode) {
             case IADD:  masm.add_s32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
             case ISUB:  masm.sub_s32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
-            case IMUL:  masm.mul_s32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case IMUL:  masm.mul_lo_s32(asIntReg(dst), asIntReg(src1),    tasm.asIntConst(src2));    break;
             case IAND:  masm.and_b32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
-            case ISHL:  masm.shl_s32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
+            case ISHL:  masm.shl_b32_const(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2));    break;
             case ISHR:  masm.shr_s32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
             case IUSHR: masm.shr_u32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
             case IXOR:  masm.xor_b32(asIntReg(dst),    asIntReg(src1),    tasm.asIntConst(src2));    break;
             case LXOR:  masm.xor_b64(asLongReg(dst),   asLongReg(src1),   tasm.asLongConst(src2));   break;
             case LUSHR: masm.shr_u64(asLongReg(dst),   asLongReg(src1),   tasm.asLongConst(src2));   break;
             case FADD:  masm.add_f32(asFloatReg(dst),  asFloatReg(src1),  tasm.asFloatConst(src2));  break;
-            case FMUL:  masm.mul_f32(asFloatReg(dst),  asFloatReg(src1),  tasm.asFloatConst(src2));  break;
+            case FMUL:  masm.mul_lo_f32(asFloatReg(dst), asFloatReg(src1), tasm.asFloatConst(src2)); break;
             case FDIV:  masm.div_f32(asFloatReg(dst),  asFloatReg(src1),  tasm.asFloatConst(src2));  break;
             case DADD:  masm.add_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break;
-            case DMUL:  masm.mul_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break;
+            case DMUL:  masm.mul_lo_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break;
             case DDIV:  masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -387,34 +387,34 @@
             // case D:  new Mul(Double, dst, src1, src2);
             case IADD:  masm.add_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
             case ISUB:  masm.sub_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
-            case IMUL:  masm.mul_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case IMUL:  masm.mul_lo_s32(asIntReg(dst), asIntReg(src1),    asIntReg(src2));    break;
             case IDIV:  masm.div_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
             case IAND:  masm.and_b32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
             case IOR:    masm.or_b32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
             case IXOR:  masm.xor_b32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
-            case ISHL:  masm.shl_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
+            case ISHL:  masm.shl_b32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
             case ISHR:  masm.shr_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
             case IUSHR: masm.shr_u32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
             case IREM:  masm.rem_s32(asIntReg(dst),    asIntReg(src1),    asIntReg(src2));    break;
             case LADD:  masm.add_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
             case LSUB:  masm.sub_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
-            case LMUL:  masm.mul_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LMUL:  masm.mul_lo_s64(asLongReg(dst), asLongReg(src1),  asLongReg(src2));   break;
             case LDIV:  masm.div_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
             case LAND:  masm.and_b64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
-            case LOR:    masm.or_b64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LOR:   masm.or_b64(asLongReg(dst),    asLongReg(src1),   asLongReg(src2));   break;
             case LXOR:  masm.xor_b64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
-            case LSHL:  masm.shl_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
+            case LSHL:  masm.shl_b64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
             case LSHR:  masm.shr_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
             case LUSHR: masm.shr_u64(asLongReg(dst),   asLongReg(src1),   asIntReg(src2));    break;
             case LREM:  masm.rem_s64(asLongReg(dst),   asLongReg(src1),   asLongReg(src2));   break;
             case FADD:  masm.add_f32(asFloatReg(dst),  asFloatReg(src1),  asFloatReg(src2));  break;
             case FSUB:  masm.sub_f32(asFloatReg(dst),  asFloatReg(src1),  asFloatReg(src2));  break;
-            case FMUL:  masm.mul_f32(asFloatReg(dst),  asFloatReg(src1),  asFloatReg(src2));  break;
+            case FMUL:  masm.mul_lo_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break;
             case FDIV:  masm.div_f32(asFloatReg(dst),  asFloatReg(src1),  asFloatReg(src2));  break;
             case FREM:  masm.div_f32(asFloatReg(dst),  asFloatReg(src1),  asFloatReg(src2));  break;
             case DADD:  masm.add_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
             case DSUB:  masm.sub_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
-            case DMUL:  masm.mul_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
+            case DMUL:  masm.mul_lo_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
             case DDIV:  masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
             case DREM:  masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
             default:
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Tue Sep 10 16:33:28 2013 -0700
@@ -55,6 +55,19 @@
         }
     }
 
+    public static class ReturnNoValOp extends PTXLIRInstruction {
+
+        public ReturnNoValOp() { }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            if (tasm.frameContext != null) {
+                tasm.frameContext.leave(tasm);
+            }
+            masm.ret();
+        }
+    }
+
     public static class BranchOp extends PTXLIRInstruction implements StandardOp.BranchOp {
 
         protected Condition condition;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMemOp.java	Tue Sep 10 16:33:28 2013 -0700
@@ -0,0 +1,264 @@
+/*
+ * 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.lir.ptx;
+
+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.ptx.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+public class PTXMemOp {
+
+    // Load operation from .global state space
+    @Opcode("LOAD")
+    public static class LoadOp extends PTXLIRInstruction {
+
+        private final Kind kind;
+        @Def({REG}) protected AllocatableValue result;
+        @Use({COMPOSITE}) protected PTXAddressValue address;
+        @State protected LIRFrameState state;
+
+        public LoadOp(Kind kind, AllocatableValue result, PTXAddressValue address, LIRFrameState state) {
+            this.kind = kind;
+            this.result = result;
+            this.address = address;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            PTXAddress addr = address.toAddress();
+            switch (kind) {
+                case Byte:
+                    masm.ld_global_s8(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Short:
+                    masm.ld_global_s16(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Char:
+                    masm.ld_global_u16(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Int:
+                    masm.ld_global_s32(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Long:
+                    masm.ld_global_s64(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Float:
+                    masm.ld_global_f32(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Double:
+                    masm.ld_global_f64(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Object:
+                    masm.ld_global_u32(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    // Store operation from .global state space
+    @Opcode("STORE")
+    public static class StoreOp extends PTXLIRInstruction {
+
+        private final Kind kind;
+        @Use({COMPOSITE}) protected PTXAddressValue address;
+        @Use({REG}) protected AllocatableValue input;
+        @State protected LIRFrameState state;
+
+        public StoreOp(Kind kind, PTXAddressValue address, AllocatableValue input, LIRFrameState state) {
+            this.kind = kind;
+            this.address = address;
+            this.input = input;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            assert isRegister(input);
+            PTXAddress addr = address.toAddress();
+            switch (kind) {
+                case Byte:
+                    masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Short:
+                    masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Int:
+                    masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Long:
+                    masm.st_global_s64(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Float:
+                    masm.st_global_f32(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Double:
+                    masm.st_global_f64(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Object:
+                    masm.st_global_u64(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere("missing: " + address.getKind());
+            }
+        }
+    }
+
+    // Load operation from .param state space
+    @Opcode("LOAD")
+    public static class LoadParamOp extends PTXLIRInstruction {
+
+        private final Kind kind;
+        @Def({REG}) protected AllocatableValue result;
+        @Use({COMPOSITE}) protected PTXAddressValue address;
+        @State protected LIRFrameState state;
+
+        public LoadParamOp(Kind kind, AllocatableValue result, PTXAddressValue address, LIRFrameState state) {
+            this.kind = kind;
+            this.result = result;
+            this.address = address;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            PTXAddress addr = address.toAddress();
+            switch (kind) {
+                case Byte:
+                    masm.ld_from_state_space(".param.s8", asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Short:
+                    masm.ld_from_state_space(".param.s16", asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Char:
+                    masm.ld_from_state_space(".param.u16", asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Int:
+                    masm.ld_from_state_space(".param.s32", asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Long:
+                    masm.ld_from_state_space(".param.s64", asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Float:
+                    masm.ld_from_state_space(".param.f32", asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Double:
+                    masm.ld_from_state_space(".param.f64", asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Object:
+                    masm.ld_from_state_space(".param.u64", asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    // Load contents of return value pointer from return argument in
+    // .param state space
+    @Opcode("LOAD_RET_ADDR")
+    public static class LoadReturnAddrOp extends PTXLIRInstruction {
+
+        private final Kind kind;
+        @Def({REG}) protected AllocatableValue result;
+        @Use({COMPOSITE}) protected PTXAddressValue address;
+        @State protected LIRFrameState state;
+
+        public LoadReturnAddrOp(Kind kind, AllocatableValue result, PTXAddressValue address, LIRFrameState state) {
+            this.kind = kind;
+            this.result = result;
+            this.address = address;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            PTXAddress addr = address.toAddress();
+            switch (kind) {
+                case Int:
+                    masm.ld_return_address("u32", asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Long:
+                    masm.ld_return_address("u64", asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    // Store operation from .global state space
+    @Opcode("STORE_RETURN_VALUE")
+    public static class StoreReturnValOp extends PTXLIRInstruction {
+
+        private final Kind kind;
+        @Use({COMPOSITE}) protected PTXAddressValue address;
+        @Use({REG}) protected AllocatableValue input;
+        @State protected LIRFrameState state;
+
+        public StoreReturnValOp(Kind kind, PTXAddressValue address, AllocatableValue input, LIRFrameState state) {
+            this.kind = kind;
+            this.address = address;
+            this.input = input;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            assert isRegister(input);
+            PTXAddress addr = address.toAddress();
+            // masm.st_global_return_value_s64(addr.getBase(), addr.getDisplacement(), asRegister(input));
+
+            switch (kind) {
+                case Byte:
+                case Short:
+                    masm.st_global_return_value_s8(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Int:
+                    masm.st_global_return_value_s32(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Long:
+                    masm.st_global_return_value_s64(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Float:
+                    masm.st_global_return_value_f32(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Double:
+                    masm.st_global_return_value_f64(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Object:
+                    masm.st_global_return_value_u64(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere("missing: " + address.getKind());
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Tue Sep 10 16:33:28 2013 -0700
@@ -116,100 +116,6 @@
         }
     }
 
-    public static class LoadOp extends PTXLIRInstruction {
-
-        private final Kind kind;
-        @Def({REG}) protected AllocatableValue result;
-        @Use({COMPOSITE}) protected PTXAddressValue address;
-        @State protected LIRFrameState state;
-
-        public LoadOp(Kind kind, AllocatableValue result, PTXAddressValue address, LIRFrameState state) {
-            this.kind = kind;
-            this.result = result;
-            this.address = address;
-            this.state = state;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
-            PTXAddress addr = address.toAddress();
-            switch (kind) {
-                case Byte:
-                    masm.ld_global_s8(asRegister(result), addr.getBase(), addr.getDisplacement());
-                    break;
-                case Short:
-                    masm.ld_global_s16(asRegister(result), addr.getBase(), addr.getDisplacement());
-                    break;
-                case Char:
-                    masm.ld_global_u16(asRegister(result), addr.getBase(), addr.getDisplacement());
-                    break;
-                case Int:
-                    masm.ld_global_s32(asRegister(result), addr.getBase(), addr.getDisplacement());
-                    break;
-                case Long:
-                    masm.ld_global_s64(asRegister(result), addr.getBase(), addr.getDisplacement());
-                    break;
-                case Float:
-                    masm.ld_global_f32(asRegister(result), addr.getBase(), addr.getDisplacement());
-                    break;
-                case Double:
-                    masm.ld_global_f64(asRegister(result), addr.getBase(), addr.getDisplacement());
-                    break;
-                case Object:
-                    masm.ld_global_u32(asRegister(result), addr.getBase(), addr.getDisplacement());
-                    break;
-                default:
-                    throw GraalInternalError.shouldNotReachHere();
-            }
-        }
-    }
-
-    public static class StoreOp extends PTXLIRInstruction {
-
-        private final Kind kind;
-        @Use({COMPOSITE}) protected PTXAddressValue address;
-        @Use({REG}) protected AllocatableValue input;
-        @State protected LIRFrameState state;
-
-        public StoreOp(Kind kind, PTXAddressValue address, AllocatableValue input, LIRFrameState state) {
-            this.kind = kind;
-            this.address = address;
-            this.input = input;
-            this.state = state;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
-            assert isRegister(input);
-            PTXAddress addr = address.toAddress();
-            switch (kind) {
-                case Byte:
-                    masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input));
-                    break;
-                case Short:
-                    masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input));
-                    break;
-                case Int:
-                    masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input));
-                    break;
-                case Long:
-                    masm.st_global_s64(addr.getBase(), addr.getDisplacement(), asRegister(input));
-                    break;
-                case Float:
-                    masm.st_global_f32(addr.getBase(), addr.getDisplacement(), asRegister(input));
-                    break;
-                case Double:
-                    masm.st_global_f64(addr.getBase(), addr.getDisplacement(), asRegister(input));
-                    break;
-                case Object:
-                    masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input));
-                    break;
-                default:
-                    throw GraalInternalError.shouldNotReachHere("missing: " + address.getKind());
-            }
-        }
-    }
-
     public static class LeaOp extends PTXLIRInstruction {
 
         @Def({REG}) protected AllocatableValue result;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXParameterOp.java	Tue Sep 10 16:33:28 2013 -0700
@@ -0,0 +1,68 @@
+/*
+ * 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.lir.ptx;
+
+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.ptx.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+public class PTXParameterOp extends LIRInstruction {
+
+    @Def({REG}) protected Value[] params;
+
+    public PTXParameterOp(Value[] params) {
+        this.params = params;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm) {
+        PTXAssembler masm = (PTXAssembler) tasm.asm;
+        // Emit parameter directives for arguments
+        int argCount = params.length;
+        for (int i = 0; i < argCount; i++) {
+            Kind paramKind = params[i].getKind();
+            switch (paramKind) {
+            case Int :
+                masm.param_32_decl(asIntReg(params[i]), (i == (argCount - 1)));
+                break;
+            case Long :
+                masm.param_64_decl(asLongReg(params[i]), (i == (argCount - 1)));
+                break;
+            case Float :
+                masm.param_32_decl(asFloatReg(params[i]), (i == (argCount - 1)));
+                break;
+            case Double :
+                masm.param_64_decl(asDoubleReg(params[i]), (i == (argCount - 1)));
+                break;
+            default :
+                throw GraalInternalError.shouldNotReachHere("unhandled parameter type "  + paramKind.toString());
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Tue Sep 10 16:33:28 2013 -0700
@@ -25,6 +25,7 @@
 import java.lang.annotation.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
@@ -45,8 +46,11 @@
 
     private final CompositeValueClass valueClass;
 
+    private static final DebugMetric COMPOSITE_VALUE_COUNT = Debug.metric("CompositeValues");
+
     public CompositeValue(PlatformKind kind) {
         super(kind);
+        COMPOSITE_VALUE_COUNT.increment();
         valueClass = CompositeValueClass.get(getClass());
     }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Tue Sep 10 16:33:28 2013 -0700
@@ -30,6 +30,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.asm.*;
 
@@ -211,10 +212,13 @@
      */
     private int id;
 
+    private static final DebugMetric LIR_NODE_COUNT = Debug.metric("LIRNodes");
+
     /**
      * Constructs a new LIR instruction.
      */
     public LIRInstruction() {
+        LIR_NODE_COUNT.increment();
         instructionClass = LIRInstructionClass.get(getClass());
         id = -1;
     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Tue Sep 10 16:33:28 2013 -0700
@@ -54,12 +54,30 @@
      */
     public static class LabelOp extends LIRInstruction {
 
+        private static final Value[] NO_VALUES = new Value[0];
+
+        /**
+         * In the LIR, every register and variable must be defined before it is used. For method
+         * parameters that are passed in fixed registers, exception objects passed to the exception
+         * handler in a fixed register, or any other use of a fixed register not defined in this
+         * method, an artificial definition is necessary. To avoid spill moves to be inserted
+         * between the label at the beginning of a block an an actual definition in the second
+         * instruction of a block, the registers are defined here in the label.
+         */
+        @Def({REG, STACK}) private Value[] incomingValues;
+
         private final Label label;
         private final boolean align;
 
         public LabelOp(Label label, boolean align) {
             this.label = label;
             this.align = align;
+            this.incomingValues = NO_VALUES;
+        }
+
+        public void setIncomingValues(Value[] values) {
+            assert incomingValues.length == 0;
+            incomingValues = values;
         }
 
         @Override
@@ -121,25 +139,6 @@
     }
 
     /**
-     * Meta-operation that defines the incoming method parameters. In the LIR, every register and
-     * variable must be defined before it is used. This operation is the definition point of method
-     * parameters, but is otherwise a no-op. In particular, it is not the actual method prologue.
-     */
-    public static final class ParametersOp extends LIRInstruction {
-
-        @Def({REG, STACK}) protected Value[] params;
-
-        public ParametersOp(Value[] params) {
-            this.params = params;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm) {
-            // No code to emit.
-        }
-    }
-
-    /**
      * Placeholder for a LIR instruction that will be subsequently replaced.
      */
     public static class PlaceholderOp extends LIRInstruction {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Tue Sep 10 16:33:28 2013 -0700
@@ -145,11 +145,11 @@
         }
     }
 
-    protected static NodeBitMap computeNodes(Graph graph, Collection<AbstractBeginNode> blocks) {
+    protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks) {
         return computeNodes(graph, blocks, Collections.<AbstractBeginNode> emptyList());
     }
 
-    protected static NodeBitMap computeNodes(Graph graph, Collection<AbstractBeginNode> blocks, Collection<AbstractBeginNode> earlyExits) {
+    protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) {
         final NodeBitMap nodes = graph.createNodeBitMap(true);
         for (AbstractBeginNode b : blocks) {
             for (Node n : b.getBlockNodes()) {
@@ -229,12 +229,28 @@
         return false;
     }
 
-    public static Collection<AbstractBeginNode> toHirBlocks(Collection<Block> blocks) {
-        List<AbstractBeginNode> hir = new ArrayList<>(blocks.size());
-        for (Block b : blocks) {
-            hir.add(b.getBeginNode());
-        }
-        return hir;
+    public static NodeIterable<AbstractBeginNode> toHirBlocks(final Iterable<Block> blocks) {
+        return new AbstractNodeIterable<AbstractBeginNode>() {
+
+            public Iterator<AbstractBeginNode> iterator() {
+                final Iterator<Block> it = blocks.iterator();
+                return new Iterator<AbstractBeginNode>() {
+
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public AbstractBeginNode next() {
+                        return it.next().getBeginNode();
+                    }
+
+                    public boolean hasNext() {
+                        return it.hasNext();
+                    }
+                };
+            }
+
+        };
     }
 
     /**
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Tue Sep 10 16:33:28 2013 -0700
@@ -231,7 +231,7 @@
         StructuredGraph graph = graph();
         if (endsToMerge.size() == 1) {
             AbstractEndNode end = endsToMerge.get(0);
-            assert end.usages().count() == 0;
+            assert end.usages().isEmpty();
             newExit = graph.add(new BeginNode());
             end.replaceAtPredecessor(newExit);
             end.safeDelete();
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Tue Sep 10 16:33:28 2013 -0700
@@ -25,13 +25,13 @@
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 public abstract class LoopTransformations {
 
@@ -53,7 +53,7 @@
         loop.inside().duplicate().insertBefore(loop);
     }
 
-    public static void fullUnroll(LoopEx loop, MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads) {
+    public static void fullUnroll(LoopEx loop, PhaseContext context, CanonicalizerPhase canonicalizer) {
         // assert loop.isCounted(); //TODO (gd) strenghten : counted with known trip count
         int iterations = 0;
         LoopBeginNode loopBegin = loop.loopBegin();
@@ -61,7 +61,7 @@
         while (!loopBegin.isDeleted()) {
             int mark = graph.getMark();
             peel(loop);
-            new CanonicalizerPhase.Instance(runtime, assumptions, canonicalizeReads, mark, null).apply(graph);
+            canonicalizer.applyIncremental(graph, context, mark);
             if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > MaximumDesiredSize.getValue() * 3) {
                 throw new BailoutException("FullUnroll : Graph seems to grow out of proportion");
             }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -26,15 +26,16 @@
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 
 public class LoopFullUnrollPhase extends BasePhase<PhaseContext> {
 
     private static final DebugMetric FULLY_UNROLLED_LOOPS = Debug.metric("FullUnrolls");
-    private final boolean canonicalizeReads;
+    private final CanonicalizerPhase canonicalizer;
 
-    public LoopFullUnrollPhase(boolean canonicalizeReads) {
-        this.canonicalizeReads = canonicalizeReads;
+    public LoopFullUnrollPhase(CanonicalizerPhase canonicalizer) {
+        this.canonicalizer = canonicalizer;
     }
 
     @Override
@@ -48,7 +49,7 @@
                 for (LoopEx loop : dataCounted.countedLoops()) {
                     if (LoopPolicies.shouldFullUnroll(loop)) {
                         Debug.log("FullUnroll %s", loop);
-                        LoopTransformations.fullUnroll(loop, context.getRuntime(), context.getAssumptions(), canonicalizeReads);
+                        LoopTransformations.fullUnroll(loop, context, canonicalizer);
                         FULLY_UNROLLED_LOOPS.increment();
                         Debug.dump(graph, "After fullUnroll %s", loop);
                         peeled = true;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -185,9 +185,4 @@
             throw new UnsupportedOperationException();
         }
     }
-
-    @Override
-    public AbstractBeginNode asNode() {
-        return this;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -77,6 +77,14 @@
     }
 
     /**
+     * Returns a node for a primitive constant.
+     */
+    public static ConstantNode forPrimitive(Constant constant, Graph graph) {
+        assert constant.getKind() != Kind.Object;
+        return forConstant(constant, null, graph);
+    }
+
+    /**
      * Returns a node for a double constant.
      * 
      * @param d the double value for which to create the instruction
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -59,7 +59,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -106,9 +106,12 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.BEFORE_GUARDS) {
-            tool.getRuntime().lower(this, tool);
+    public void lower(LoweringTool tool) {
+        if (graph().getGuardsPhase() == StructuredGraph.GuardsPhase.FLOATING_GUARDS) {
+            GuardingNode guard = tool.createGuard(condition(), getReason(), getAction(), isNegated());
+            ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(guard.asNode()));
+            this.replaceAtUsages(guard.asNode());
+            graph().replaceFixedWithFixed(this, newAnchor);
         } else {
             FixedNode next = next();
             setNext(null);
@@ -130,11 +133,6 @@
     }
 
     @Override
-    public FixedGuardNode asNode() {
-        return this;
-    }
-
-    @Override
     public boolean canDeoptimize() {
         return true;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -35,4 +35,9 @@
         assertTrue(this.successors().isNotEmpty() || this.predecessor() != null, "FixedNode should not float");
         return super.verify();
     }
+
+    @Override
+    public FixedNode asNode() {
+        return this;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -49,10 +49,4 @@
         updateUsages(this.guard == null ? null : this.guard.asNode(), guard == null ? null : guard.asNode());
         this.guard = guard;
     }
-
-    @Override
-    public FloatingNode asNode() {
-        return this;
-    }
-
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -76,8 +76,8 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.AFTER_GUARDS) {
+    public void lower(LoweringTool tool) {
+        if (graph().getGuardsPhase() == StructuredGraph.GuardsPhase.FIXED_DEOPTS) {
             throw new GraalInternalError("Cannot create guards in after-guard lowering");
         }
         FixedGuardNode guard = graph().add(new FixedGuardNode(condition, reason, action, negated));
@@ -115,11 +115,6 @@
                     @ConstantNodeParameter DeoptimizationAction action, @ConstantNodeParameter Stamp stamp);
 
     @Override
-    public ValueNode asNode() {
-        return this;
-    }
-
-    @Override
     public ValueNode getOriginalValue() {
         return object;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -23,14 +23,14 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.graph.Node.IterableNodeType;
+import com.oracle.graal.graph.Node;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
  * Nodes of this type are inserted into the graph to denote points of interest to debugging.
  */
-public class InfopointNode extends AbstractStateSplit implements LIRLowerable, IterableNodeType {
+public class InfopointNode extends AbstractStateSplit implements LIRLowerable, Node.IterableNodeType {
 
     public final InfopointReason reason;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -108,7 +108,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
@@ -133,11 +133,6 @@
     }
 
     @Override
-    public FixedNode asNode() {
-        return this;
-    }
-
-    @Override
     public FrameState stateDuring() {
         FrameState stateAfter = stateAfter();
         if (stateAfter == null) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -119,11 +119,6 @@
     }
 
     @Override
-    public FixedNode asNode() {
-        return this;
-    }
-
-    @Override
     public void setNext(FixedNode x) {
         if (x != null) {
             this.setNext(AbstractBeginNode.begin(x));
@@ -133,7 +128,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -30,4 +30,22 @@
     public LogicNode() {
         super(StampFactory.condition());
     }
+
+    public static LogicNode and(LogicNode a, LogicNode b, double shortCircuitProbability) {
+        return and(a, false, b, false, shortCircuitProbability);
+    }
+
+    public static LogicNode and(LogicNode a, boolean negateA, LogicNode b, boolean negateB, double shortCircuitProbability) {
+        StructuredGraph graph = a.graph();
+        ShortCircuitOrNode notAorNotB = graph.unique(new ShortCircuitOrNode(a, !negateA, b, !negateB, shortCircuitProbability));
+        return graph.unique(new LogicNegationNode(notAorNotB));
+    }
+
+    public static LogicNode or(LogicNode a, LogicNode b, double shortCircuitProbability) {
+        return or(a, false, b, false, shortCircuitProbability);
+    }
+
+    public static LogicNode or(LogicNode a, boolean negateA, LogicNode b, boolean negateB, double shortCircuitProbability) {
+        return a.graph().unique(new ShortCircuitOrNode(a, negateA, b, negateB, shortCircuitProbability));
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -72,7 +72,7 @@
     @Override
     public boolean verify() {
         assertTrue(loopBegin != null, "must have a loop begin");
-        assertTrue(usages().count() == 0, "LoopEnds can not be used");
+        assertTrue(usages().isEmpty(), "LoopEnds can not be used");
         return super.verify();
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -34,7 +34,7 @@
  * variable.
  */
 @NodeInfo(nameTemplate = "{p#type/s}Phi({i#values})")
-public final class PhiNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType, GuardingNode {
+public class PhiNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType, GuardingNode {
 
     public static enum PhiType {
         Value(null), // normal value phis
@@ -248,9 +248,4 @@
     public boolean isLoopPhi() {
         return merge() instanceof LoopBeginNode;
     }
-
-    @Override
-    public PhiNode asNode() {
-        return this;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -120,8 +120,4 @@
     public ValueNode getOriginalValue() {
         return value;
     }
-
-    public ValueNode asNode() {
-        return this;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitAndNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2013, 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.nodes;
-
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * The short-circuit <b>AND</b> (i.e. {@code &&} in Java) operator.
- */
-public class ShortCircuitAndNode extends ShortCircuitBooleanNode implements Canonicalizable {
-
-    public ShortCircuitAndNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, double shortCircuitProbability) {
-        super(x, xNegated, y, yNegated, shortCircuitProbability);
-    }
-
-    @Override
-    public LogicNode canonical(CanonicalizerTool tool) {
-        ShortCircuitBooleanNode ret = canonicalizeNegation();
-        if (ret != null) {
-            return ret;
-        }
-
-        LogicNode x = getX();
-        LogicNode y = getY();
-        if (x == y) {
-            // @formatter:off
-            //  a &&  a = a
-            //  a && !a = false
-            // !a &&  a = false
-            // !a && !a = !a
-            // @formatter:on
-            if (isXNegated()) {
-                if (isYNegated()) {
-                    // !a && !a = !a
-                    return graph().unique(new LogicNegationNode(x));
-                } else {
-                    // !a && a = false
-                    return LogicConstantNode.contradiction(graph());
-                }
-            } else {
-                if (isYNegated()) {
-                    // a && !a = false
-                    return LogicConstantNode.contradiction(graph());
-                } else {
-                    // a && a = a
-                    return x;
-                }
-            }
-        }
-        if (x instanceof LogicConstantNode) {
-            if (((LogicConstantNode) x).getValue() ^ isXNegated()) {
-                if (isYNegated()) {
-                    return graph().unique(new LogicNegationNode(y));
-                } else {
-                    return y;
-                }
-            } else {
-                return LogicConstantNode.contradiction(graph());
-            }
-        }
-        if (y instanceof LogicConstantNode) {
-            if (((LogicConstantNode) y).getValue() ^ isYNegated()) {
-                if (isXNegated()) {
-                    return graph().unique(new LogicNegationNode(x));
-                } else {
-                    return x;
-                }
-            } else {
-                return LogicConstantNode.contradiction(graph());
-            }
-        }
-        return this;
-    }
-
-    @Override
-    protected ShortCircuitBooleanNode createCopy(LogicNode xCond, boolean xNeg, LogicNode yCond, boolean yNeg, double probability) {
-        return new ShortCircuitAndNode(xCond, xNeg, yCond, yNeg, probability);
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitBooleanNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2013, 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.nodes;
-
-import com.oracle.graal.graph.*;
-
-/**
- * Base class for the short-circuit boolean operators.
- */
-public abstract class ShortCircuitBooleanNode extends LogicNode implements Node.IterableNodeType {
-
-    @Input private LogicNode x;
-    @Input private LogicNode y;
-    private boolean xNegated;
-    private boolean yNegated;
-    private double shortCircuitProbability;
-
-    public ShortCircuitBooleanNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, double shortCircuitProbability) {
-        this.x = x;
-        this.xNegated = xNegated;
-        this.y = y;
-        this.yNegated = yNegated;
-        this.shortCircuitProbability = shortCircuitProbability;
-    }
-
-    public LogicNode getX() {
-        return x;
-    }
-
-    public LogicNode getY() {
-        return y;
-    }
-
-    public boolean isXNegated() {
-        return xNegated;
-    }
-
-    public boolean isYNegated() {
-        return yNegated;
-    }
-
-    /**
-     * Gets the probability that the {@link #getY() y} part of this binary node is <b>not</b>
-     * evaluated. This is the probability that this operator will short-circuit its execution.
-     */
-    public double getShortCircuitProbability() {
-        return shortCircuitProbability;
-    }
-
-    protected abstract ShortCircuitBooleanNode createCopy(LogicNode xCond, boolean xNeg, LogicNode yCond, boolean yNeg, double probability);
-
-    protected ShortCircuitBooleanNode canonicalizeNegation() {
-        LogicNode xCond = x;
-        boolean xNeg = xNegated;
-        while (xCond instanceof LogicNegationNode) {
-            xCond = ((LogicNegationNode) xCond).getInput();
-            xNeg = !xNeg;
-        }
-
-        LogicNode yCond = y;
-        boolean yNeg = yNegated;
-        while (yCond instanceof LogicNegationNode) {
-            yCond = ((LogicNegationNode) yCond).getInput();
-            yNeg = !yNeg;
-        }
-
-        if (xCond != x || yCond != y) {
-            return graph().unique(createCopy(xCond, xNeg, yCond, yNeg, shortCircuitProbability));
-        } else {
-            return null;
-        }
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,27 +22,79 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
 
-/**
- * The short-circuit <b>OR</b> (i.e. {@code ||} in Java) operator.
- */
-public class ShortCircuitOrNode extends ShortCircuitBooleanNode implements Canonicalizable {
+public class ShortCircuitOrNode extends LogicNode implements Node.IterableNodeType, Canonicalizable {
+
+    @Input private LogicNode x;
+    @Input private LogicNode y;
+    private boolean xNegated;
+    private boolean yNegated;
+    private double shortCircuitProbability;
 
     public ShortCircuitOrNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, double shortCircuitProbability) {
-        super(x, xNegated, y, yNegated, shortCircuitProbability);
+        this.x = x;
+        this.xNegated = xNegated;
+        this.y = y;
+        this.yNegated = yNegated;
+        this.shortCircuitProbability = shortCircuitProbability;
+    }
+
+    public LogicNode getX() {
+        return x;
+    }
+
+    public LogicNode getY() {
+        return y;
+    }
+
+    public boolean isXNegated() {
+        return xNegated;
+    }
+
+    public boolean isYNegated() {
+        return yNegated;
+    }
+
+    /**
+     * Gets the probability that the {@link #getY() y} part of this binary node is <b>not</b>
+     * evaluated. This is the probability that this operator will short-circuit its execution.
+     */
+    public double getShortCircuitProbability() {
+        return shortCircuitProbability;
+    }
+
+    protected ShortCircuitOrNode canonicalizeNegation() {
+        LogicNode xCond = x;
+        boolean xNeg = xNegated;
+        while (xCond instanceof LogicNegationNode) {
+            xCond = ((LogicNegationNode) xCond).getInput();
+            xNeg = !xNeg;
+        }
+
+        LogicNode yCond = y;
+        boolean yNeg = yNegated;
+        while (yCond instanceof LogicNegationNode) {
+            yCond = ((LogicNegationNode) yCond).getInput();
+            yNeg = !yNeg;
+        }
+
+        if (xCond != x || yCond != y) {
+            return graph().unique(new ShortCircuitOrNode(xCond, xNeg, yCond, yNeg, shortCircuitProbability));
+        } else {
+            return null;
+        }
     }
 
     @Override
     public LogicNode canonical(CanonicalizerTool tool) {
-        ShortCircuitBooleanNode ret = canonicalizeNegation();
+        ShortCircuitOrNode ret = canonicalizeNegation();
         if (ret != null) {
             return ret;
         }
 
-        LogicNode x = getX();
-        LogicNode y = getY();
-        if (x == y) {
+        if (getX() == getY()) {
             // @formatter:off
             //  a ||  a = a
             //  a || !a = true
@@ -52,7 +104,7 @@
             if (isXNegated()) {
                 if (isYNegated()) {
                     // !a || !a = !a
-                    return graph().unique(new LogicNegationNode(x));
+                    return graph().unique(new LogicNegationNode(getX()));
                 } else {
                     // !a || a = true
                     return LogicConstantNode.tautology(graph());
@@ -63,37 +115,32 @@
                     return LogicConstantNode.tautology(graph());
                 } else {
                     // a || a = a
-                    return x;
+                    return getX();
                 }
             }
         }
-        if (x instanceof LogicConstantNode) {
-            if (((LogicConstantNode) x).getValue() ^ isXNegated()) {
+        if (getX() instanceof LogicConstantNode) {
+            if (((LogicConstantNode) getX()).getValue() ^ isXNegated()) {
                 return LogicConstantNode.tautology(graph());
             } else {
                 if (isYNegated()) {
-                    return graph().unique(new LogicNegationNode(y));
+                    return graph().unique(new LogicNegationNode(getY()));
                 } else {
-                    return y;
+                    return getY();
                 }
             }
         }
-        if (y instanceof LogicConstantNode) {
-            if (((LogicConstantNode) y).getValue() ^ isYNegated()) {
+        if (getY() instanceof LogicConstantNode) {
+            if (((LogicConstantNode) getY()).getValue() ^ isYNegated()) {
                 return LogicConstantNode.tautology(graph());
             } else {
                 if (isXNegated()) {
-                    return graph().unique(new LogicNegationNode(x));
+                    return graph().unique(new LogicNegationNode(getX()));
                 } else {
-                    return x;
+                    return getX();
                 }
             }
         }
         return this;
     }
-
-    @Override
-    protected ShortCircuitBooleanNode createCopy(LogicNode xCond, boolean xNeg, LogicNode yCond, boolean yNeg, double probability) {
-        return new ShortCircuitOrNode(xCond, xNeg, yCond, yNeg, probability);
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Tue Sep 10 16:33:28 2013 -0700
@@ -37,6 +37,10 @@
  */
 public class StructuredGraph extends Graph {
 
+    public static enum GuardsPhase {
+        FLOATING_GUARDS, FIXED_DEOPTS, AFTER_FSA
+    }
+
     public static final int INVOCATION_ENTRY_BCI = -1;
     public static final long INVALID_GRAPH_ID = -1;
 
@@ -48,6 +52,7 @@
     private final ResolvedJavaMethod method;
     private final long graphId;
     private final int entryBCI;
+    private GuardsPhase guardsPhase = GuardsPhase.FLOATING_GUARDS;
 
     /**
      * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start()
@@ -144,15 +149,19 @@
         return copy(name);
     }
 
-    @Override
-    public StructuredGraph copy(String newName) {
-        StructuredGraph copy = new StructuredGraph(newName, method, graphId, entryBCI);
+    public StructuredGraph copy(String newName, ResolvedJavaMethod newMethod) {
+        StructuredGraph copy = new StructuredGraph(newName, newMethod, graphId, entryBCI);
         HashMap<Node, Node> replacements = new HashMap<>();
         replacements.put(start, copy.start);
         copy.addDuplicates(getNodes(), replacements);
         return copy;
     }
 
+    @Override
+    public StructuredGraph copy(String newName) {
+        return copy(newName, method);
+    }
+
     public LocalNode getLocal(int index) {
         for (LocalNode local : getNodes(LocalNode.class)) {
             if (local.index() == index) {
@@ -382,4 +391,13 @@
             singleEnd.replaceAndDelete(sux);
         }
     }
+
+    public GuardsPhase getGuardsPhase() {
+        return guardsPhase;
+    }
+
+    public void setGuardsPhase(GuardsPhase guardsPhase) {
+        assert guardsPhase.ordinal() >= this.guardsPhase.ordinal();
+        this.guardsPhase = guardsPhase;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -50,7 +50,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -140,4 +140,8 @@
         assertTrue(kind() == kind().getStackKind(), "Should have a stack kind : %s", kind());
         return super.verify();
     }
+
+    public ValueNode asNode() {
+        return this;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/WriteBarrier.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/WriteBarrier.java	Tue Sep 10 16:33:28 2013 -0700
@@ -53,8 +53,8 @@
     }
 
     @Override
-    public void lower(LoweringTool generator, LoweringType loweringType) {
-        assert loweringType == LoweringType.AFTER_FSA;
+    public void lower(LoweringTool generator) {
+        assert graph().getGuardsPhase() == StructuredGraph.GuardsPhase.AFTER_FSA;
         generator.getRuntime().lower(this, generator);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -83,6 +83,57 @@
         }
     }
 
+    public static BinaryNode add(ValueNode x, ValueNode y) {
+        assert x.kind() == y.kind();
+        switch (x.kind()) {
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+            case Long:
+                return IntegerArithmeticNode.add(x, y);
+            case Float:
+            case Double:
+                return x.graph().unique(new FloatAddNode(x.kind(), x, y, false));
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    public static BinaryNode sub(ValueNode x, ValueNode y) {
+        assert x.kind() == y.kind();
+        switch (x.kind()) {
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+            case Long:
+                return IntegerArithmeticNode.sub(x, y);
+            case Float:
+            case Double:
+                return x.graph().unique(new FloatSubNode(x.kind(), x, y, false));
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    public static BinaryNode mul(ValueNode x, ValueNode y) {
+        assert x.kind() == y.kind();
+        switch (x.kind()) {
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+            case Long:
+                return IntegerArithmeticNode.mul(x, y);
+            case Float:
+            case Double:
+                return x.graph().unique(new FloatMulNode(x.kind(), x, y, false));
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
     public static boolean canTryReassociate(BinaryNode node) {
         return node instanceof IntegerAddNode || node instanceof IntegerSubNode || node instanceof IntegerMulNode || node instanceof AndNode || node instanceof OrNode || node instanceof XorNode;
     }
@@ -99,14 +150,22 @@
         return null;
     }
 
+    //@formatter:off
     /*
      * In reassociate, complexity comes from the handling of IntegerSub (non commutative) which can
-     * be mixed with IntegerAdd. if first tries to find m1, m2 which match the criterion : (a o m2)
-     * o m1 (m2 o a) o m1 m1 o (a o m2) m1 o (m2 o a) It then produces 4 boolean for the -/+ case
-     * invertA : should the final expression be like *-a (rather than a+*) aSub : should the final
-     * expression be like a-* (rather than a+*) invertM1 : should the final expression contain -m1
+     * be mixed with IntegerAdd. It first tries to find m1, m2 which match the criterion :
+     * (a o m2) o m1
+     * (m2 o a) o m1
+     * m1 o (a o m2)
+     * m1 o (m2 o a)
+     * It then produces 4 boolean for the -/+ cases:
+     * invertA : should the final expression be like *-a (rather than a+*)
+     * aSub : should the final expression be like a-* (rather than a+*)
+     * invertM1 : should the final expression contain -m1
      * invertM2 : should the final expression contain -m2
+     *
      */
+    //@formatter:on
     /**
      * Tries to re-associate values which satisfy the criterion. For example with a constantness
      * criterion : (a + 2) + 1 => a + (1 + 2)<br>
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -235,7 +235,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -110,7 +110,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -61,7 +61,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -48,7 +48,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         LogicNode equalComp;
         LogicNode lessComp;
         if (x().kind() == Kind.Double || x().kind() == Kind.Float) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -62,7 +62,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -61,7 +61,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -166,7 +166,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         if (!enabled) {
             throw new GraalInternalError("counter nodes shouldn't exist when not enabled");
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -78,11 +78,6 @@
     }
 
     @Override
-    public AccessNode asNode() {
-        return this;
-    }
-
-    @Override
     public boolean canDeoptimize() {
         return nullCheck;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -53,7 +53,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -123,7 +123,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         throw new GraalInternalError("Branch probability could not be injected, because the probability value did not reduce to a constant value.");
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -70,11 +70,6 @@
     }
 
     @Override
-    public FloatingAccessNode asNode() {
-        return this;
-    }
-
-    @Override
     public boolean canDeoptimize() {
         return nullCheck;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -58,8 +58,8 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.AFTER_GUARDS) {
+    public void lower(LoweringTool tool) {
+        if (graph().getGuardsPhase() == StructuredGraph.GuardsPhase.FIXED_DEOPTS) {
             tool.getRuntime().lower(this, tool);
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -51,7 +51,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -54,9 +54,4 @@
     public DeoptimizationReason getDeoptimizationReason() {
         return DeoptimizationReason.NullCheckException;
     }
-
-    @Override
-    public ValueNode asNode() {
-        return this;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -29,7 +29,7 @@
 public class OSRStartNode extends StartNode implements Lowerable {
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -72,7 +72,7 @@
 
     public static ValueNode canonicalizeRead(ValueNode read, LocationNode location, ValueNode object, CanonicalizerTool tool, boolean compressible) {
         MetaAccessProvider runtime = tool.runtime();
-        if (read.usages().count() == 0) {
+        if (read.usages().isEmpty()) {
             // Read without usages can be savely removed.
             return null;
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -46,7 +46,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -48,7 +48,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -49,7 +49,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -68,7 +68,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -114,9 +114,4 @@
         }
         tool.delete();
     }
-
-    @Override
-    public ValueNode asNode() {
-        return this;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -88,7 +88,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -83,7 +83,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -64,7 +64,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -62,7 +62,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -59,7 +59,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -96,7 +96,7 @@
      * {@code LoweringPhase.checkUsagesAreScheduled()}.
      */
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         InstanceOfNode typeTest = graph().add(new InstanceOfNode(type, object, profile));
         Stamp stamp = StampFactory.declared(type);
         if (stamp() instanceof ObjectStamp && object().stamp() instanceof ObjectStamp) {
@@ -118,7 +118,7 @@
             } else {
                 // TODO (ds) replace with probability of null-seen when available
                 double shortCircuitProbability = NOT_FREQUENT_PROBABILITY;
-                condition = graph().unique(new ShortCircuitOrNode(graph().unique(new IsNullNode(object)), false, typeTest, false, shortCircuitProbability));
+                condition = LogicNode.or(graph().unique(new IsNullNode(object)), typeTest, shortCircuitProbability);
             }
         }
         GuardingPiNode checkedObject = graph().add(new GuardingPiNode(object, condition, false, forStoreCheck ? ArrayStoreException : ClassCastException, InvalidateReprofile, stamp));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -78,7 +78,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -64,7 +64,7 @@
      * runtime/interpreter would not have a valid location for the exception object to be rethrown.
      */
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         if (isLowered()) {
             return;
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -23,9 +23,7 @@
 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.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -52,7 +50,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
@@ -74,12 +72,4 @@
     public ValueNode mirror() {
         return mirror;
     }
-
-    @Override
-    public boolean verify() {
-        for (Node usage : usages()) {
-            assertTrue(usage instanceof IfNode || usage instanceof FixedGuardNode || usage instanceof ConditionalNode, "unsupported usage: %s", usage);
-        }
-        return super.verify();
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -51,7 +51,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -44,7 +44,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -50,7 +50,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -51,7 +51,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -77,7 +77,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
@@ -85,7 +85,7 @@
     public void virtualize(VirtualizerTool tool) {
         if (instanceClass != null) {
             assert !instanceClass().isArray();
-            VirtualInstanceNode virtualObject = new VirtualInstanceNode(instanceClass());
+            VirtualInstanceNode virtualObject = new VirtualInstanceNode(instanceClass(), true);
             ResolvedJavaField[] fields = virtualObject.getFields();
             ValueNode[] state = new ValueNode[fields.length];
             for (int i = 0; i < state.length; i++) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -62,7 +62,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -28,7 +28,7 @@
 import com.oracle.graal.api.meta.ResolvedJavaMethod;
 import com.oracle.graal.graph.GraalInternalError;
 import com.oracle.graal.graph.NodeInputList;
-import com.oracle.graal.nodes.ValueNode;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.LIRGeneratorTool;
 import com.oracle.graal.nodes.spi.Lowerable;
 import com.oracle.graal.nodes.spi.LoweringTool;
@@ -68,7 +68,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         InvokeKind invokeKind = Modifier.isStatic(replacementTargetMethod.getModifiers()) ? InvokeKind.Static : InvokeKind.Special;
         MethodCallTargetNode replacement = graph().add(
                         new MethodCallTargetNode(invokeKind, replacementTargetMethod, replacementArguments.toArray(new ValueNode[replacementArguments.size()]), replacementReturnType));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.nodes.spi;
 
+import com.oracle.graal.nodes.*;
+
 public interface Lowerable {
 
-    public enum LoweringType {
-        BEFORE_GUARDS, AFTER_GUARDS, AFTER_FSA
-    }
+    void lower(LoweringTool tool);
 
-    void lower(LoweringTool tool, LoweringType loweringType);
+    ValueNode asNode();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Tue Sep 10 16:33:28 2013 -0700
@@ -28,14 +28,11 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 
 public interface LoweringTool {
 
     GraalCodeCacheProvider getRuntime();
 
-    LoweringType getLoweringType();
-
     Replacements getReplacements();
 
     GuardingNode createNullCheckGuard(GuardedNode guardedNode, ValueNode object);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -65,7 +65,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -36,6 +36,7 @@
     private final int length;
 
     public VirtualArrayNode(ResolvedJavaType componentType, int length) {
+        super(true);
         this.componentType = componentType;
         this.length = length;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -31,7 +31,7 @@
     private final Kind boxingKind;
 
     public VirtualBoxingNode(ResolvedJavaType type, Kind boxingKind) {
-        super(type);
+        super(type, false);
         this.boxingKind = boxingKind;
     }
 
@@ -41,11 +41,6 @@
     }
 
     @Override
-    public boolean hasIdentity() {
-        return false;
-    }
-
-    @Override
     public ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, int[] locks) {
         assert entries.length == 1;
         assert locks.length == 0;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -32,12 +32,12 @@
     private final ResolvedJavaType type;
     private final ResolvedJavaField[] fields;
 
-    public VirtualInstanceNode(ResolvedJavaType type) {
-        this.type = type;
-        this.fields = type.getInstanceFields(true);
+    public VirtualInstanceNode(ResolvedJavaType type, boolean hasIdentity) {
+        this(type, type.getInstanceFields(true), hasIdentity);
     }
 
-    public VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) {
+    public VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields, boolean hasIdentity) {
+        super(hasIdentity);
         this.type = type;
         this.fields = fields;
     }
@@ -97,7 +97,7 @@
 
     @Override
     public VirtualInstanceNode duplicate() {
-        return new VirtualInstanceNode(type);
+        return new VirtualInstanceNode(type, fields, super.hasIdentity());
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -23,14 +23,18 @@
 package com.oracle.graal.nodes.virtual;
 
 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.*;
 
-public abstract class VirtualObjectNode extends ValueNode implements LIRLowerable {
+public abstract class VirtualObjectNode extends ValueNode implements LIRLowerable, Node.IterableNodeType {
+
+    private boolean hasIdentity;
 
-    public VirtualObjectNode() {
+    public VirtualObjectNode(boolean hasIdentity) {
         super(StampFactory.virtual());
+        this.hasIdentity = hasIdentity;
     }
 
     /**
@@ -72,7 +76,11 @@
      * comparison of two virtual objects is determined by comparing their contents.
      */
     public boolean hasIdentity() {
-        return true;
+        return hasIdentity;
+    }
+
+    public void setIdentity(boolean identity) {
+        this.hasIdentity = identity;
     }
 
     /**
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -31,24 +31,25 @@
 import com.oracle.graal.graph.Graph.NodeChangedListener;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.tiers.*;
 
 public class CanonicalizerPhase extends BasePhase<PhaseContext> {
 
     private static final int MAX_ITERATION_PER_NODE = 10;
     private static final DebugMetric METRIC_CANONICALIZED_NODES = Debug.metric("CanonicalizedNodes");
+    private static final DebugMetric METRIC_PROCESSED_NODES = Debug.metric("ProcessedNodes");
     private static final DebugMetric METRIC_CANONICALIZATION_CONSIDERED_NODES = Debug.metric("CanonicalizationConsideredNodes");
     private static final DebugMetric METRIC_INFER_STAMP_CALLED = Debug.metric("InferStampCalled");
     private static final DebugMetric METRIC_STAMP_CHANGED = Debug.metric("StampChanged");
     private static final DebugMetric METRIC_SIMPLIFICATION_CONSIDERED_NODES = Debug.metric("SimplificationConsideredNodes");
-    public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits");
+    private static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits");
 
     private final boolean canonicalizeReads;
+    private final CustomCanonicalizer customCanonicalizer;
 
     public interface CustomCanonicalizer {
 
@@ -56,15 +57,57 @@
     }
 
     public CanonicalizerPhase(boolean canonicalizeReads) {
+        this(canonicalizeReads, null);
+    }
+
+    public CanonicalizerPhase(boolean canonicalizeReads, CustomCanonicalizer customCanonicalizer) {
         this.canonicalizeReads = canonicalizeReads;
+        this.customCanonicalizer = customCanonicalizer;
     }
 
     @Override
     protected void run(StructuredGraph graph, PhaseContext context) {
-        new Instance(context.getRuntime(), context.getAssumptions(), canonicalizeReads).run(graph);
+        new Instance(context.getRuntime(), context.getAssumptions(), canonicalizeReads, customCanonicalizer).run(graph);
+    }
+
+    /**
+     * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by this
+     *            mark are processed
+     */
+    public void applyIncremental(StructuredGraph graph, PhaseContext context, int newNodesMark) {
+        applyIncremental(graph, context, newNodesMark, true);
+    }
+
+    public void applyIncremental(StructuredGraph graph, PhaseContext context, int newNodesMark, boolean dumpGraph) {
+        new Instance(context.getRuntime(), context.getAssumptions(), canonicalizeReads, newNodesMark, customCanonicalizer).apply(graph, dumpGraph);
     }
 
-    public static class Instance extends Phase {
+    /**
+     * @param workingSet the initial working set of nodes on which the canonicalizer works, should
+     *            be an auto-grow node bitmap
+     */
+    public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable<Node> workingSet) {
+        applyIncremental(graph, context, workingSet, true);
+    }
+
+    public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable<Node> workingSet, boolean dumpGraph) {
+        new Instance(context.getRuntime(), context.getAssumptions(), canonicalizeReads, workingSet, customCanonicalizer).apply(graph, dumpGraph);
+    }
+
+    public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable<Node> workingSet, int newNodesMark) {
+        applyIncremental(graph, context, workingSet, newNodesMark, true);
+    }
+
+    public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable<Node> workingSet, int newNodesMark, boolean dumpGraph) {
+        new Instance(context.getRuntime(), context.getAssumptions(), canonicalizeReads, workingSet, newNodesMark, customCanonicalizer).apply(graph, dumpGraph);
+    }
+
+    @Deprecated
+    public void addToPhasePlan(PhasePlan plan, PhaseContext context) {
+        plan.addPhase(PhasePosition.AFTER_PARSING, new Instance(context.getRuntime(), context.getAssumptions(), canonicalizeReads, customCanonicalizer));
+    }
+
+    private static final class Instance extends Phase {
 
         private final int newNodesMark;
         private final Assumptions assumptions;
@@ -76,34 +119,19 @@
         private NodeWorkList workList;
         private Tool tool;
 
-        public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads) {
-            this(runtime, assumptions, canonicalizeReads, null, 0, null);
+        private Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, CustomCanonicalizer customCanonicalizer) {
+            this(runtime, assumptions, canonicalizeReads, null, 0, customCanonicalizer);
         }
 
-        /**
-         * @param runtime
-         * @param assumptions
-         * @param workingSet the initial working set of nodes on which the canonicalizer works,
-         *            should be an auto-grow node bitmap
-         * @param customCanonicalizer
-         * @param canonicalizeReads flag to indicate if
-         *            {@link LoadFieldNode#canonical(CanonicalizerTool)} and
-         *            {@link ReadNode#canonical(CanonicalizerTool)} should canonicalize reads of
-         *            constant fields.
-         */
-        public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, Iterable<Node> workingSet, CustomCanonicalizer customCanonicalizer) {
+        private Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, Iterable<Node> workingSet, CustomCanonicalizer customCanonicalizer) {
             this(runtime, assumptions, canonicalizeReads, workingSet, 0, customCanonicalizer);
         }
 
-        /**
-         * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by
-         *            this mark are processed otherwise all nodes in the graph are processed
-         */
-        public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
+        private Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
             this(runtime, assumptions, canonicalizeReads, null, newNodesMark, customCanonicalizer);
         }
 
-        public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
+        private Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
             super("Canonicalizer");
             this.newNodesMark = newNodesMark;
             this.assumptions = assumptions;
@@ -160,14 +188,13 @@
                     if (!tryCanonicalize(node)) {
                         if (node instanceof ValueNode) {
                             ValueNode valueNode = (ValueNode) node;
-                            if (tryInferStamp(valueNode)) {
-                                Constant constant = valueNode.stamp().asConstant();
-                                if (constant != null) {
-                                    performReplacement(valueNode, ConstantNode.forConstant(constant, runtime, valueNode.graph()));
-                                } else {
-                                    // the improved stamp may enable additional canonicalization
-                                    tryCanonicalize(valueNode);
-                                }
+                            boolean improvedStamp = tryInferStamp(valueNode);
+                            Constant constant = valueNode.stamp().asConstant();
+                            if (constant != null && !(node instanceof ConstantNode)) {
+                                performReplacement(valueNode, ConstantNode.forConstant(constant, runtime, valueNode.graph()));
+                            } else if (improvedStamp) {
+                                // the improved stamp may enable additional canonicalization
+                                tryCanonicalize(valueNode);
                             }
                         }
                     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -110,9 +110,6 @@
 
     private static void iterateInputs(NodeFlood flood, StructuredGraph graph) {
         for (Node node : graph.getNodes()) {
-            if (node instanceof LocalNode) {
-                flood.add(node);
-            }
             if (flood.isMarked(node)) {
                 for (Node input : node.inputs()) {
                     flood.add(input);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -31,33 +31,21 @@
 
     @Override
     protected void run(StructuredGraph graph) {
-        for (ShortCircuitBooleanNode logic : graph.getNodes(ShortCircuitBooleanNode.class)) {
+        for (ShortCircuitOrNode logic : graph.getNodes(ShortCircuitOrNode.class)) {
             processBinary(logic);
         }
-        assert graph.getNodes(ShortCircuitBooleanNode.class).isEmpty();
+        assert graph.getNodes(ShortCircuitOrNode.class).isEmpty();
     }
 
-    private static void processBinary(ShortCircuitBooleanNode binary) {
+    private static void processBinary(ShortCircuitOrNode binary) {
         while (binary.usages().isNotEmpty()) {
             Node usage = binary.usages().first();
-            if (usage instanceof ShortCircuitBooleanNode) {
-                processBinary((ShortCircuitBooleanNode) usage);
+            if (usage instanceof ShortCircuitOrNode) {
+                processBinary((ShortCircuitOrNode) usage);
             } else if (usage instanceof IfNode) {
-                if (binary instanceof ShortCircuitAndNode) {
-                    processIf(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (IfNode) usage, false, binary.getShortCircuitProbability());
-                } else if (binary instanceof ShortCircuitOrNode) {
-                    processIf(binary.getX(), !binary.isXNegated(), binary.getY(), !binary.isYNegated(), (IfNode) usage, true, binary.getShortCircuitProbability());
-                } else {
-                    throw GraalInternalError.shouldNotReachHere();
-                }
+                processIf(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (IfNode) usage, binary.getShortCircuitProbability());
             } else if (usage instanceof ConditionalNode) {
-                if (binary instanceof ShortCircuitOrNode) {
-                    processConditional(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (ConditionalNode) usage, false);
-                } else if (binary instanceof ShortCircuitOrNode) {
-                    processConditional(binary.getX(), !binary.isXNegated(), binary.getY(), !binary.isYNegated(), (ConditionalNode) usage, true);
-                } else {
-                    throw GraalInternalError.shouldNotReachHere();
-                }
+                processConditional(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (ConditionalNode) usage);
             } else {
                 throw GraalInternalError.shouldNotReachHere();
             }
@@ -65,33 +53,44 @@
         binary.safeDelete();
     }
 
-    private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, boolean negateTargets, double shortCircuitProbability) {
-        AbstractBeginNode trueTarget = negateTargets ? ifNode.falseSuccessor() : ifNode.trueSuccessor();
-        AbstractBeginNode falseTarget = negateTargets ? ifNode.trueSuccessor() : ifNode.falseSuccessor();
+    private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, double shortCircuitProbability) {
+        AbstractBeginNode trueTarget = ifNode.trueSuccessor();
+        AbstractBeginNode falseTarget = ifNode.falseSuccessor();
         double firstIfProbability = shortCircuitProbability;
-        double secondIfProbability = 1 - ifNode.probability(trueTarget);
+        /*
+         * P(Y | not(X)) = P(Y inter not(X)) / P(not(X)) = (P(X union Y) - P(X)) / (1 - P(X))
+         * 
+         * P(X) = shortCircuitProbability
+         * 
+         * P(X union Y) = ifNode.probability(trueTarget)
+         */
+        double secondIfProbability = (ifNode.probability(trueTarget) - shortCircuitProbability) / (1 - shortCircuitProbability);
+        secondIfProbability = Math.min(1.0, Math.max(0.0, secondIfProbability));
+        if (Double.isNaN(secondIfProbability)) {
+            secondIfProbability = 0.5;
+        }
         ifNode.clearSuccessors();
         Graph graph = ifNode.graph();
-        MergeNode falseTargetMerge = graph.add(new MergeNode());
-        falseTargetMerge.setNext(falseTarget);
-        EndNode firstFalseEnd = graph.add(new EndNode());
-        EndNode secondFalseEnd = graph.add(new EndNode());
-        falseTargetMerge.addForwardEnd(firstFalseEnd);
-        falseTargetMerge.addForwardEnd(secondFalseEnd);
-        AbstractBeginNode firstFalseTarget = AbstractBeginNode.begin(firstFalseEnd);
-        AbstractBeginNode secondFalseTarget = AbstractBeginNode.begin(secondFalseEnd);
-        AbstractBeginNode secondIf = AbstractBeginNode.begin(graph.add(new IfNode(y, yNegated ? firstFalseTarget : trueTarget, yNegated ? trueTarget : firstFalseTarget, secondIfProbability)));
-        IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondFalseTarget : secondIf, xNegated ? secondIf : secondFalseTarget, firstIfProbability));
+        MergeNode trueTargetMerge = graph.add(new MergeNode());
+        trueTargetMerge.setNext(trueTarget);
+        EndNode firstTrueEnd = graph.add(new EndNode());
+        EndNode secondTrueEnd = graph.add(new EndNode());
+        trueTargetMerge.addForwardEnd(firstTrueEnd);
+        trueTargetMerge.addForwardEnd(secondTrueEnd);
+        AbstractBeginNode firstTrueTarget = AbstractBeginNode.begin(firstTrueEnd);
+        AbstractBeginNode secondTrueTarget = AbstractBeginNode.begin(secondTrueEnd);
+        AbstractBeginNode secondIf = AbstractBeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfProbability)));
+        IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfProbability));
         ifNode.replaceAtPredecessor(firstIf);
         ifNode.safeDelete();
     }
 
-    private static void processConditional(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, ConditionalNode conditional, boolean negateTargets) {
-        ValueNode trueTarget = negateTargets ? conditional.falseValue() : conditional.trueValue();
-        ValueNode falseTarget = negateTargets ? conditional.trueValue() : conditional.falseValue();
+    private static void processConditional(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, ConditionalNode conditional) {
+        ValueNode trueTarget = conditional.trueValue();
+        ValueNode falseTarget = conditional.falseValue();
         Graph graph = conditional.graph();
         ConditionalNode secondConditional = graph.unique(new ConditionalNode(y, yNegated ? falseTarget : trueTarget, yNegated ? trueTarget : falseTarget));
-        ConditionalNode firstConditional = graph.unique(new ConditionalNode(x, xNegated ? falseTarget : secondConditional, xNegated ? secondConditional : falseTarget));
+        ConditionalNode firstConditional = graph.unique(new ConditionalNode(x, xNegated ? secondConditional : trueTarget, xNegated ? trueTarget : secondConditional));
         conditional.replaceAndDelete(firstConditional);
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.GuardsPhase;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.graph.*;
@@ -77,6 +78,8 @@
     protected void run(StructuredGraph graph) {
         assert checkFixedDeopts(graph);
         ReentrantNodeIterator.apply(new FrameStateAssignmentClosure(), graph.start(), null, null);
+
+        graph.setGuardsPhase(GuardsPhase.AFTER_FSA);
     }
 
     private static boolean checkFixedDeopts(StructuredGraph graph) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -29,6 +29,7 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.GuardsPhase;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
@@ -187,6 +188,8 @@
         for (Block block : schedule.getCFG().getBlocks()) {
             processBlock(block, schedule, context.getTarget().implicitNullCheckLimit);
         }
+
+        graph.setGuardsPhase(GuardsPhase.FIXED_DEOPTS);
     }
 
     private static void processBlock(Block block, SchedulePhase schedule, int implicitNullCheckLimit) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,29 +22,42 @@
  */
 package com.oracle.graal.phases.common;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import java.util.*;
 
+import com.oracle.graal.graph.Graph.NodeChangedListener;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
 import com.oracle.graal.phases.tiers.*;
 
 public class IncrementalCanonicalizerPhase<C extends PhaseContext> extends PhaseSuite<C> {
 
-    private final CustomCanonicalizer customCanonicalizer;
+    private final CanonicalizerPhase canonicalizer;
 
-    public IncrementalCanonicalizerPhase() {
-        this(null);
-    }
-
-    public IncrementalCanonicalizerPhase(CustomCanonicalizer customCanonicalizer) {
-        this.customCanonicalizer = customCanonicalizer;
+    public IncrementalCanonicalizerPhase(CanonicalizerPhase canonicalizer) {
+        this.canonicalizer = canonicalizer;
     }
 
     @Override
     protected void run(StructuredGraph graph, C context) {
-        int mark = graph.getMark();
+        int newNodesMark = graph.getMark();
+        final Set<Node> changedNodes = new HashSet<>();
+
+        NodeChangedListener listener = new NodeChangedListener() {
+
+            @Override
+            public void nodeChanged(Node node) {
+                changedNodes.add(node);
+            }
+        };
+        graph.trackInputChange(listener);
+        graph.trackUsagesDroppedZero(listener);
+
         super.run(graph, context);
-        new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), !AOTCompilation.getValue(), mark, customCanonicalizer).apply(graph);
+
+        graph.stopTrackingInputChange();
+        graph.stopTrackingUsagesDroppedZero();
+
+        canonicalizer.applyIncremental(graph, context, changedNodes, newNodesMark, false);
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -39,7 +39,6 @@
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
-import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
 import com.oracle.graal.phases.common.InliningUtil.InlineInfo;
 import com.oracle.graal.phases.common.InliningUtil.Inlineable;
 import com.oracle.graal.phases.common.InliningUtil.InlineableGraph;
@@ -59,7 +58,7 @@
     }
 
     private final InliningPolicy inliningPolicy;
-    private final CustomCanonicalizer customCanonicalizer;
+    private final CanonicalizerPhase canonicalizer;
 
     private int inliningCount;
     private int maxMethodPerInlining = Integer.MAX_VALUE;
@@ -70,25 +69,17 @@
     private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize");
     private static final DebugMetric metricInliningRuns = Debug.metric("Runs");
 
-    public InliningPhase() {
-        this(new GreedyInliningPolicy(null), null);
-    }
-
-    public InliningPhase(CustomCanonicalizer canonicalizer) {
+    public InliningPhase(CanonicalizerPhase canonicalizer) {
         this(new GreedyInliningPolicy(null), canonicalizer);
     }
 
-    public InliningPhase(Map<Invoke, Double> hints) {
-        this(new GreedyInliningPolicy(hints), null);
+    public InliningPhase(Map<Invoke, Double> hints, CanonicalizerPhase canonicalizer) {
+        this(new GreedyInliningPolicy(hints), canonicalizer);
     }
 
-    public InliningPhase(InliningPolicy policy) {
-        this(policy, null);
-    }
-
-    private InliningPhase(InliningPolicy policy, CustomCanonicalizer customCanonicalizer) {
+    public InliningPhase(InliningPolicy policy, CanonicalizerPhase canonicalizer) {
         this.inliningPolicy = policy;
-        this.customCanonicalizer = customCanonicalizer;
+        this.canonicalizer = canonicalizer;
     }
 
     public void setMaxMethodsPerInlining(int max) {
@@ -163,7 +154,7 @@
             MethodInvocation calleeInvocation = data.pushInvocation(info, parentAssumptions, invokeProbability, invokeRelevance);
 
             for (int i = 0; i < info.numberOfMethods(); i++) {
-                Inlineable elem = getInlineableElement(info.methodAt(i), info.invoke(), calleeInvocation.assumptions(), context);
+                Inlineable elem = getInlineableElement(info.methodAt(i), info.invoke(), context.replaceAssumptions(calleeInvocation.assumptions()));
                 info.setInlinableElement(i, elem);
                 if (elem instanceof InlineableGraph) {
                     data.pushGraph(((InlineableGraph) elem).getGraph(), invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i));
@@ -200,7 +191,7 @@
 
             if (OptCanonicalizer.getValue()) {
                 int markBeforeCanonicalization = callerGraph.getMark();
-                new CanonicalizerPhase.Instance(context.getRuntime(), callerAssumptions, !AOTCompilation.getValue(), invokeUsages, markBeforeInlining, customCanonicalizer).apply(callerGraph);
+                canonicalizer.applyIncremental(callerGraph, context, invokeUsages, markBeforeInlining);
 
                 // process invokes that are possibly created during canonicalization
                 for (Node newNode : callerGraph.getNewNodes(markBeforeCanonicalization)) {
@@ -223,16 +214,16 @@
         }
     }
 
-    private static Inlineable getInlineableElement(final ResolvedJavaMethod method, Invoke invoke, Assumptions assumptions, HighTierContext context) {
+    private Inlineable getInlineableElement(final ResolvedJavaMethod method, Invoke invoke, HighTierContext context) {
         Class<? extends FixedWithNextNode> macroNodeClass = InliningUtil.getMacroNodeClass(context.getReplacements(), method);
         if (macroNodeClass != null) {
             return new InlineableMacroNode(macroNodeClass);
         } else {
-            return new InlineableGraph(buildGraph(method, invoke, assumptions, context));
+            return new InlineableGraph(buildGraph(method, invoke, context));
         }
     }
 
-    private static StructuredGraph buildGraph(final ResolvedJavaMethod method, final Invoke invoke, final Assumptions assumptions, final HighTierContext context) {
+    private StructuredGraph buildGraph(final ResolvedJavaMethod method, final Invoke invoke, final HighTierContext context) {
         final StructuredGraph newGraph;
         final boolean parseBytecodes;
 
@@ -258,7 +249,7 @@
             @Override
             public StructuredGraph call() throws Exception {
                 if (parseBytecodes) {
-                    parseBytecodes(newGraph, assumptions, context);
+                    parseBytecodes(newGraph, context);
                 }
 
                 boolean callerHasMoreInformationAboutArguments = false;
@@ -285,7 +276,7 @@
                 }
 
                 if (OptCanonicalizer.getValue()) {
-                    new CanonicalizerPhase.Instance(context.getRuntime(), assumptions, !AOTCompilation.getValue()).apply(newGraph);
+                    canonicalizer.apply(newGraph, context);
                 }
 
                 return newGraph;
@@ -303,7 +294,7 @@
         return null;
     }
 
-    private static StructuredGraph parseBytecodes(StructuredGraph newGraph, Assumptions assumptions, HighTierContext context) {
+    private StructuredGraph parseBytecodes(StructuredGraph newGraph, HighTierContext context) {
         boolean hasMatureProfilingInfo = newGraph.method().getProfilingInfo().isMature();
 
         if (context.getPhasePlan() != null) {
@@ -314,7 +305,7 @@
         new DeadCodeEliminationPhase().apply(newGraph);
 
         if (OptCanonicalizer.getValue()) {
-            new CanonicalizerPhase.Instance(context.getRuntime(), assumptions, !AOTCompilation.getValue()).apply(newGraph);
+            canonicalizer.apply(newGraph, context);
         }
 
         if (CacheGraphs.getValue() && context.getGraphCache() != null) {
@@ -512,7 +503,7 @@
             while ((current = nextQueuedNode()) != null) {
                 assert current.isAlive();
 
-                if (current instanceof Invoke) {
+                if (current instanceof Invoke && ((Invoke) current).callTarget() instanceof MethodCallTargetNode) {
                     if (current != start) {
                         invokes.addLast((Invoke) current);
                     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Tue Sep 10 16:33:28 2013 -0700
@@ -38,7 +38,7 @@
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.*;
+import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -707,7 +707,8 @@
                 if (opportunities > 0) {
                     metricInliningTailDuplication.increment();
                     Debug.log("MultiTypeGuardInlineInfo starting tail duplication (%d opportunities)", opportunities);
-                    TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacementNodes, new PhaseContext(runtime, assumptions, replacements));
+                    TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacementNodes, new PhaseContext(runtime, assumptions, replacements), new CanonicalizerPhase(
+                                    !AOTCompilation.getValue()));
                 }
             }
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.phases.common;
 
-import static com.oracle.graal.phases.GraalOptions.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -36,6 +34,12 @@
 
     private static final int MAX_ITERATIONS = 256;
 
+    private final CanonicalizerPhase canonicalizer;
+
+    public IterativeConditionalEliminationPhase(CanonicalizerPhase canonicalizer) {
+        this.canonicalizer = canonicalizer;
+    }
+
     @Override
     protected void run(StructuredGraph graph, PhaseContext context) {
         ConditionalEliminationPhase eliminate = new ConditionalEliminationPhase(context.getRuntime());
@@ -55,7 +59,7 @@
                     listener.getChangedNodes().add(node);
                 }
             }
-            new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), !AOTCompilation.getValue(), listener.getChangedNodes(), null).apply(graph);
+            canonicalizer.applyIncremental(graph, context, listener.getChangedNodes());
             listener.getChangedNodes().clear();
             if (++count > MAX_ITERATIONS) {
                 throw new BailoutException("Number of iterations in conditional elimination phase exceeds " + MAX_ITERATIONS);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -35,7 +35,6 @@
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.schedule.*;
@@ -54,10 +53,11 @@
         private FixedWithNextNode lastFixedNode;
         private ControlFlowGraph cfg;
 
-        public LoweringToolImpl(PhaseContext context, GuardingNode guardAnchor, NodeBitMap activeGuards, ControlFlowGraph cfg) {
+        public LoweringToolImpl(PhaseContext context, GuardingNode guardAnchor, NodeBitMap activeGuards, FixedWithNextNode lastFixedNode, ControlFlowGraph cfg) {
             this.context = context;
             this.guardAnchor = guardAnchor;
             this.activeGuards = activeGuards;
+            this.lastFixedNode = lastFixedNode;
             this.cfg = cfg;
         }
 
@@ -72,11 +72,6 @@
         }
 
         @Override
-        public LoweringType getLoweringType() {
-            return loweringType;
-        }
-
-        @Override
         public GuardingNode createNullCheckGuard(GuardedNode guardedNode, ValueNode object) {
             if (ObjectStamp.isObjectNonNull(object)) {
                 // Short cut creation of null check guard if the object is known to be non-null.
@@ -100,8 +95,8 @@
 
         @Override
         public GuardingNode createGuard(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
-            if (loweringType != LoweringType.BEFORE_GUARDS) {
-                throw new GraalInternalError("Cannot create guards in after-guard lowering");
+            if (condition.graph().getGuardsPhase().ordinal() > StructuredGraph.GuardsPhase.FLOATING_GUARDS.ordinal()) {
+                throw new GraalInternalError("Cannot create guards after guard lowering");
             }
             if (OptEliminateGuards.getValue()) {
                 for (Node usage : condition.usages()) {
@@ -133,11 +128,10 @@
         }
     }
 
-    private final LoweringType loweringType;
+    private final CanonicalizerPhase canonicalizer;
 
-    public LoweringPhase(LoweringType loweringType) {
-        super("Lowering (" + loweringType.name() + ")");
-        this.loweringType = loweringType;
+    public LoweringPhase(CanonicalizerPhase canonicalizer) {
+        this.canonicalizer = canonicalizer;
     }
 
     private static boolean containsLowerable(NodeIterable<Node> nodes) {
@@ -153,12 +147,11 @@
     protected void run(final StructuredGraph graph, PhaseContext context) {
         int i = 0;
         while (true) {
-            Round round = new Round(i++, context);
             int mark = graph.getMark();
 
-            IncrementalCanonicalizerPhase<PhaseContext> canonicalizer = new IncrementalCanonicalizerPhase<>();
-            canonicalizer.appendPhase(round);
-            canonicalizer.apply(graph, context);
+            IncrementalCanonicalizerPhase<PhaseContext> incrementalCanonicalizer = new IncrementalCanonicalizerPhase<>(canonicalizer);
+            incrementalCanonicalizer.appendPhase(new Round(i++, context));
+            incrementalCanonicalizer.apply(graph, context);
 
             if (!containsLowerable(graph.getNewNodes(mark))) {
                 // No new lowerable nodes - done!
@@ -216,11 +209,10 @@
 
         private void process(final Block b, final NodeBitMap activeGuards, final GuardingNode anchor) {
 
-            final LoweringToolImpl loweringTool = new LoweringToolImpl(context, anchor, activeGuards, schedule.getCFG());
+            final LoweringToolImpl loweringTool = new LoweringToolImpl(context, anchor, activeGuards, b.getBeginNode(), schedule.getCFG());
 
             // Lower the instructions of this block.
             List<ScheduledNode> nodes = schedule.nodesFor(b);
-            loweringTool.setLastFixedNode(b.getBeginNode());
             for (Node node : nodes) {
 
                 if (node.isDeleted()) {
@@ -239,7 +231,7 @@
 
                 if (node instanceof Lowerable) {
                     assert checkUsagesAreScheduled(node);
-                    ((Lowerable) node).lower(loweringTool, loweringType);
+                    ((Lowerable) node).lower(loweringTool);
                 }
 
                 if (!nextNode.isAlive()) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/RemoveValueProxyPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/RemoveValueProxyPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -39,7 +39,7 @@
             FrameState stateAfter = exit.stateAfter();
             if (stateAfter != null) {
                 exit.setStateAfter(null);
-                if (stateAfter.usages().count() == 0) {
+                if (stateAfter.usages().isEmpty()) {
                     stateAfter.safeDelete();
                 }
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -42,8 +42,8 @@
 
 /**
  * This class is a phase that looks for opportunities for tail duplication. The static method
- * {@link #tailDuplicate(MergeNode, TailDuplicationDecision, List, PhaseContext)} can also be used
- * to drive tail duplication from other places, e.g., inlining.
+ * {@link #tailDuplicate(MergeNode, TailDuplicationDecision, List, PhaseContext, CanonicalizerPhase)}
+ * can also be used to drive tail duplication from other places, e.g., inlining.
  */
 public class TailDuplicationPhase extends BasePhase<PhaseContext> {
 
@@ -53,6 +53,8 @@
     private static final DebugMetric metricDuplicationConsidered = Debug.metric("DuplicationConsidered");
     private static final DebugMetric metricDuplicationPerformed = Debug.metric("DuplicationPerformed");
 
+    private final CanonicalizerPhase canonicalizer;
+
     /**
      * This interface is used by tail duplication to let clients decide if tail duplication should
      * be performed.
@@ -129,6 +131,10 @@
         }
     };
 
+    public TailDuplicationPhase(CanonicalizerPhase canonicalizer) {
+        this.canonicalizer = canonicalizer;
+    }
+
     @Override
     protected void run(StructuredGraph graph, PhaseContext phaseContext) {
         NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(graph).apply();
@@ -137,7 +143,7 @@
         // duplication.
         for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) {
             if (!(merge instanceof LoopBeginNode) && nodeProbabilities.get(merge) >= TailDuplicationProbability.getValue()) {
-                tailDuplicate(merge, DEFAULT_DECISION, null, phaseContext);
+                tailDuplicate(merge, DEFAULT_DECISION, null, phaseContext, canonicalizer);
             }
         }
     }
@@ -159,7 +165,7 @@
      *            {@link PiNode} in the duplicated branch that corresponds to the entry.
      * @param phaseContext
      */
-    public static boolean tailDuplicate(MergeNode merge, TailDuplicationDecision decision, List<GuardedValueNode> replacements, PhaseContext phaseContext) {
+    public static boolean tailDuplicate(MergeNode merge, TailDuplicationDecision decision, List<GuardedValueNode> replacements, PhaseContext phaseContext, CanonicalizerPhase canonicalizer) {
         assert !(merge instanceof LoopBeginNode);
         assert replacements == null || replacements.size() == merge.forwardEndCount();
         FixedNode fixed = merge;
@@ -172,7 +178,7 @@
             metricDuplicationConsidered.increment();
             if (decision.doTransform(merge, fixedCount)) {
                 metricDuplicationPerformed.increment();
-                new DuplicationOperation(merge, replacements).duplicate(phaseContext);
+                new DuplicationOperation(merge, replacements, canonicalizer).duplicate(phaseContext);
                 return true;
             }
         }
@@ -190,6 +196,8 @@
         private final HashMap<ValueNode, PhiNode> bottomPhis = new HashMap<>();
         private final List<GuardedValueNode> replacements;
 
+        private final CanonicalizerPhase canonicalizer;
+
         /**
          * Initializes the tail duplication operation without actually performing any work.
          * 
@@ -197,10 +205,11 @@
          * @param replacements A list of replacement {@link PiNode}s, or null. If this is non-null,
          *            then the size of the list needs to match the number of end nodes at the merge.
          */
-        public DuplicationOperation(MergeNode merge, List<GuardedValueNode> replacements) {
+        public DuplicationOperation(MergeNode merge, List<GuardedValueNode> replacements, CanonicalizerPhase canonicalizer) {
             this.merge = merge;
             this.replacements = replacements;
             this.graph = merge.graph();
+            this.canonicalizer = canonicalizer;
         }
 
         /**
@@ -289,7 +298,7 @@
                     phi.setMerge(mergeAfter);
                 }
             }
-            new CanonicalizerPhase.Instance(phaseContext.getRuntime(), phaseContext.getAssumptions(), !AOTCompilation.getValue(), graph.getNewNodes(startMark), null).apply(graph);
+            canonicalizer.applyIncremental(graph, phaseContext, startMark);
             Debug.dump(graph, "After tail duplication at %s", merge);
         }
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -33,8 +33,8 @@
 public abstract class BasePhase<C> {
 
     private String name;
+
     private static final DebugMetric metricPhaseRuns = Debug.metric("Runs");
-    protected static final DebugMetric METRIC_PROCESSED_NODES = Debug.metric("ProcessedNodes");
 
     protected BasePhase() {
         this.name = this.getClass().getSimpleName();
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Tue Sep 10 16:33:28 2013 -0700
@@ -89,12 +89,12 @@
     @Option(help = "")
     public static final OptionValue<Integer> DeoptsToDisableOptimisticOptimization = new OptionValue<>(40);
 
-    // comilation queue
-    @Option(help = "")
+    // compilation queue
+    @Option(help = "Compile all methods in all classes on given class path")
     public static final OptionValue<String> CompileTheWorld = new OptionValue<>(null);
-    @Option(help = "")
+    @Option(help = "First class to consider when using CompileTheWorld")
     public static final OptionValue<Integer> CompileTheWorldStartAt = new OptionValue<>(1);
-    @Option(help = "")
+    @Option(help = "Last class to consider when using CompileTheWorld")
     public static final OptionValue<Integer> CompileTheWorldStopAt = new OptionValue<>(Integer.MAX_VALUE);
 
     // graph caching
@@ -290,33 +290,6 @@
     @Option(help = "")
     public static final OptionValue<Boolean> OptPushThroughPi = new OptionValue<>(true);
 
-    // Intrinsification settings
-    @Option(help = "")
-    public static final OptionValue<Boolean> IntrinsifyObjectClone = new OptionValue<>(false);
-    @Option(help = "")
-    public static final OptionValue<Boolean> IntrinsifyArrayCopy = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> IntrinsifyObjectMethods = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> IntrinsifySystemMethods = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> IntrinsifyClassMethods = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> IntrinsifyThreadMethods = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> IntrinsifyUnsafeMethods = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> IntrinsifyMathMethods = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> IntrinsifyAESMethods = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> IntrinsifyCRC32Methods = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> IntrinsifyReflectionMethods = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> IntrinsifyInstalledCodeMethods = new OptionValue<>(true);
-    @Option(help = "")
-    public static final OptionValue<Boolean> IntrinsifyCallSiteTarget = new OptionValue<>(true);
 
     /**
      * Counts the various paths taken through snippets.
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -861,7 +861,7 @@
     private static List<ScheduledNode> filterSchedulableNodes(List<ScheduledNode> list) {
         List<ScheduledNode> result = new ArrayList<>();
         for (ScheduledNode n : list) {
-            if (!(n instanceof LocalNode) && !(n instanceof PhiNode)) {
+            if (!(n instanceof PhiNode)) {
                 result.add(n);
             }
         }
@@ -984,7 +984,7 @@
     }
 
     private void addToLatestSorting(Block b, ScheduledNode i, List<ScheduledNode> sortedInstructions, NodeBitMap visited, List<FloatingReadNode> reads, NodeBitMap beforeLastLocation) {
-        if (i == null || visited.isMarked(i) || cfg.getNodeToBlock().get(i) != b || i instanceof PhiNode || i instanceof LocalNode) {
+        if (i == null || visited.isMarked(i) || cfg.getNodeToBlock().get(i) != b || i instanceof PhiNode) {
             return;
         }
 
@@ -1045,7 +1045,7 @@
     private void addToEarliestSorting(Block b, ScheduledNode i, List<ScheduledNode> sortedInstructions, NodeBitMap visited) {
         ScheduledNode instruction = i;
         while (true) {
-            if (instruction == null || visited.isMarked(instruction) || cfg.getNodeToBlock().get(instruction) != b || instruction instanceof PhiNode || instruction instanceof LocalNode) {
+            if (instruction == null || visited.isMarked(instruction) || cfg.getNodeToBlock().get(instruction) != b || instruction instanceof PhiNode) {
                 return;
             }
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java	Tue Sep 10 16:33:28 2013 -0700
@@ -52,4 +52,8 @@
     public OptimisticOptimizations getOptimisticOptimizations() {
         return optimisticOpts;
     }
+
+    public HighTierContext replaceAssumptions(Assumptions newAssumptions) {
+        return new HighTierContext(getRuntime(), newAssumptions, getReplacements(), getGraphCache(), getPhasePlan(), getOptimisticOptimizations());
+    }
 }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -53,7 +53,7 @@
                 Assumptions assumptions = new Assumptions(true);
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, phasePlan, OptimisticOptimizations.ALL);
                 Debug.dump(graph, "Graph");
-                new InliningPhase().apply(graph, context);
+                new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 Debug.dump(graph, "Graph");
                 new CanonicalizerPhase(true).apply(graph, context);
                 new DeadCodeEliminationPhase().apply(graph);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Tue Sep 10 16:33:28 2013 -0700
@@ -93,7 +93,7 @@
      */
     protected InstanceOfUsageReplacer createReplacer(FloatingNode instanceOf, Instantiation instantiation, Node usage, final StructuredGraph graph) {
         InstanceOfUsageReplacer replacer;
-        if (usage instanceof IfNode || usage instanceof FixedGuardNode || usage instanceof ShortCircuitBooleanNode || usage instanceof GuardingPiNode) {
+        if (usage instanceof IfNode || usage instanceof FixedGuardNode || usage instanceof ShortCircuitOrNode || usage instanceof GuardingPiNode) {
             replacer = new NonMaterializationUsageReplacer(instantiation, ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph), instanceOf, usage);
         } else {
             assert usage instanceof ConditionalNode : "unexpected usage of " + instanceOf + ": " + usage;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -67,7 +67,7 @@
         }
     }
 
-    private boolean tryIntrinsify(MethodCallTargetNode methodCallTargetNode, List<Node> cleanUpReturnList) {
+    protected boolean tryIntrinsify(MethodCallTargetNode methodCallTargetNode, List<Node> cleanUpReturnList) {
         ResolvedJavaMethod target = methodCallTargetNode.targetMethod();
         NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class);
         ResolvedJavaType declaringClass = target.getDeclaringClass();
@@ -94,7 +94,7 @@
 
             // Clean up checkcast instructions inserted by javac if the return type is generic.
             cleanUpReturnList.add(newInstance);
-        } else if (target.getAnnotation(Fold.class) != null) {
+        } else if (isFoldable(target)) {
             ResolvedJavaType[] parameterTypes = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(target), declaringClass);
 
             // Prepare the arguments for the reflective method call
@@ -128,9 +128,16 @@
     }
 
     /**
+     * Permits a subclass to override the default definition of "foldable".
+     */
+    protected boolean isFoldable(ResolvedJavaMethod method) {
+        return method.getAnnotation(Fold.class) != null;
+    }
+
+    /**
      * Converts the arguments of an invoke node to object values suitable for use as the arguments
      * to a reflective invocation of a Java constructor or method.
-     * 
+     *
      * @param folding specifies if the invocation is for handling a {@link Fold} annotation
      * @return the arguments for the reflective invocation or null if an argument of {@code invoke}
      *         that is expected to be constant isn't
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Tue Sep 10 16:33:28 2013 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.replacements;
 
 import static com.oracle.graal.api.meta.MetaUtil.*;
+import static com.oracle.graal.compiler.GraalCompiler.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.reflect.*;
@@ -43,6 +44,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.Snippet.DefaultSnippetInliningPolicy;
 import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
 import com.oracle.graal.word.phases.*;
@@ -138,7 +140,7 @@
                 Member originalMethod = originalMethod(classSubstitution, methodSubstitution.optional(), originalName, originalParameters);
                 if (originalMethod != null) {
                     ResolvedJavaMethod original = registerMethodSubstitution(originalMethod, substituteMethod);
-                    if (original != null && methodSubstitution.forced()) {
+                    if (original != null && methodSubstitution.forced() && shouldIntrinsify(original)) {
                         forcedSubstitutions.add(original);
                     }
                 }
@@ -149,7 +151,7 @@
                 Member originalMethod = originalMethod(classSubstitution, macroSubstitution.optional(), originalName, originalParameters);
                 if (originalMethod != null) {
                     ResolvedJavaMethod original = registerMacroSubstitution(originalMethod, macroSubstitution.macro());
-                    if (original != null && macroSubstitution.forced()) {
+                    if (original != null && macroSubstitution.forced() && shouldIntrinsify(original)) {
                         forcedSubstitutions.add(original);
                     }
                 }
@@ -159,7 +161,7 @@
 
     /**
      * Registers a method substitution.
-     * 
+     *
      * @param originalMember a method or constructor being substituted
      * @param substituteMethod the substitute method
      * @return the original method
@@ -180,7 +182,7 @@
 
     /**
      * Registers a macro substitution.
-     * 
+     *
      * @param originalMethod a method or constructor being substituted
      * @param macro the substitute macro node class
      * @return the original method
@@ -214,7 +216,7 @@
 
     /**
      * Creates a preprocessed graph for a snippet or method substitution.
-     * 
+     *
      * @param method the snippet or method substitution for which a graph will be created
      * @param original the original method if {@code method} is a {@linkplain MethodSubstitution
      *            substitution} otherwise null
@@ -330,23 +332,28 @@
                     new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph);
                     if (OptCanonicalizer.getValue()) {
                         new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
-                        new CanonicalizerPhase.Instance(runtime, assumptions, true).apply(graph);
+                        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime, assumptions, ReplacementsImpl.this));
                     }
                 }
             });
             return graph;
         }
 
+        protected Object beforeInline(@SuppressWarnings("unused") MethodCallTargetNode callTarget, @SuppressWarnings("unused") StructuredGraph callee) {
+            return null;
+        }
+
         /**
          * Called after a graph is inlined.
-         * 
+         *
          * @param caller the graph into which {@code callee} was inlined
          * @param callee the graph that was inlined into {@code caller}
+         * @param beforeInlineData value returned by {@link #beforeInline}.
          */
-        protected void afterInline(StructuredGraph caller, StructuredGraph callee) {
+        protected void afterInline(StructuredGraph caller, StructuredGraph callee, Object beforeInlineData) {
             if (OptCanonicalizer.getValue()) {
                 new WordTypeRewriterPhase(runtime, target.wordKind).apply(caller);
-                new CanonicalizerPhase.Instance(runtime, assumptions, true).apply(caller);
+                new CanonicalizerPhase(true).apply(caller, new PhaseContext(runtime, assumptions, ReplacementsImpl.this));
             }
         }
 
@@ -360,7 +367,7 @@
 
             new DeadCodeEliminationPhase().apply(graph);
             if (OptCanonicalizer.getValue()) {
-                new CanonicalizerPhase.Instance(runtime, assumptions, true).apply(graph);
+                new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime, assumptions, ReplacementsImpl.this));
             }
         }
 
@@ -379,7 +386,7 @@
                             InliningUtil.inline(callTarget.invoke(), originalGraph, true);
 
                             Debug.dump(graph, "after inlining %s", callee);
-                            afterInline(graph, originalGraph);
+                            afterInline(graph, originalGraph, null);
                             substituteCallsOriginal = true;
                         } else {
                             StructuredGraph intrinsicGraph = InliningUtil.getIntrinsicGraph(ReplacementsImpl.this, callee);
@@ -396,9 +403,10 @@
                                     }
                                     targetGraph = parseGraph(callee, policy);
                                 }
+                                Object beforeInlineData = beforeInline(callTarget, targetGraph);
                                 InliningUtil.inline(callTarget.invoke(), targetGraph, true);
                                 Debug.dump(graph, "after inlining %s", callee);
-                                afterInline(graph, targetGraph);
+                                afterInline(graph, targetGraph, beforeInlineData);
                             }
                         }
                     }
@@ -426,7 +434,7 @@
 
     /**
      * Resolves a name to a class.
-     * 
+     *
      * @param className the name of the class to resolve
      * @param optional if true, resolution failure returns null
      * @return the resolved class or null if resolution fails and {@code optional} is true
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Sep 10 16:33:28 2013 -0700
@@ -41,6 +41,7 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.Snippet.VarargsParameter;
 import com.oracle.graal.replacements.nodes.*;
@@ -388,6 +389,8 @@
         ResolvedJavaMethod method = snippetGraph.method();
         Signature signature = method.getSignature();
 
+        PhaseContext context = new PhaseContext(runtime, replacements.getAssumptions(), replacements);
+
         // Copy snippet graph, replacing constant parameters with given arguments
         StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method());
         IdentityHashMap<Node, Node> nodeReplacements = new IdentityHashMap<>();
@@ -425,7 +428,7 @@
             new NodeIntrinsificationPhase(runtime).apply(snippetCopy);
             new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy);
 
-            new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), true, 0, null).apply(snippetCopy);
+            new CanonicalizerPhase(true).apply(snippetCopy, context);
         }
         NodeIntrinsificationVerificationPhase.verify(snippetCopy);
 
@@ -481,8 +484,8 @@
                 if (loopBegin != null) {
                     LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin);
                     int mark = snippetCopy.getMark();
-                    LoopTransformations.fullUnroll(loop, runtime, replacements.getAssumptions(), true);
-                    new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), true, mark, null).apply(snippetCopy);
+                    LoopTransformations.fullUnroll(loop, context, new CanonicalizerPhase(true));
+                    new CanonicalizerPhase(true).applyIncremental(snippetCopy, context, mark);
                 }
                 FixedNode explodeLoopNext = explodeLoop.next();
                 explodeLoop.clearSuccessors();
@@ -528,8 +531,6 @@
         ReturnNode retNode = null;
         StartNode entryPointNode = snippet.start();
 
-        new DeadCodeEliminationPhase().apply(snippetCopy);
-
         nodes = new ArrayList<>(snippet.getNodeCount());
         for (Node node : snippet.getNodes()) {
             if (node == entryPointNode || node == entryPointNode.stateAfter()) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -64,7 +64,7 @@
     public static native void storeInt(Object obj, @ConstantNodeParameter int displacement, long offset, int value);
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, value.kind(), displacement, offset, graph(), 1);
         WriteNode write = graph().add(new WriteNode(object, value, location, BarrierType.NONE, value.kind() == Kind.Object));
         graph().replaceFixedWithFixed(this, write);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -79,7 +79,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         boolean nullCheck = false;
         StructuredGraph replacementGraph = getSnippetGraph(tool);
         if (replacementGraph == null) {
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -36,7 +36,6 @@
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.common.*;
@@ -118,7 +117,7 @@
                             if (ex.counted().isConstantMaxTripCount()) {
                                 long constant = ex.counted().constantMaxTripCount();
                                 if (constant <= UNROLL_LIMIT) {
-                                    LoopTransformations.fullUnroll(ex, runtime, assumptions, canonicalizeReads);
+                                    LoopTransformations.fullUnroll(ex, context, canonicalizer);
                                     Debug.dump(resultGraph, "After loop unrolling %d times", constant);
 
                                     canonicalizer.apply(resultGraph, context);
@@ -131,7 +130,7 @@
                 }
 
                 new DeadCodeEliminationPhase().apply(resultGraph);
-                new PartialEscapePhase(true).apply(resultGraph, context);
+                new PartialEscapePhase(true, canonicalizer).apply(resultGraph, context);
 
                 if (TruffleInlinePrinter.getValue()) {
                     InlinePrinterProcessor.printTree();
@@ -161,7 +160,7 @@
             frameState.replaceAtUsages(null);
             frameState.safeDelete();
         }
-        new CanonicalizerPhase.Instance(runtime, new Assumptions(false), true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime, new Assumptions(false), replacements));
         new DeadCodeEliminationPhase().apply(graph);
     }
 
@@ -169,34 +168,36 @@
 
         StructuredGraph graphResult = Debug.scope("Truffle", new DebugDumpScope("Comparison: " + methodName), new Callable<StructuredGraph>() {
 
+            @SuppressWarnings("deprecation")
             public StructuredGraph call() {
                 Assumptions assumptions = new Assumptions(false);
                 StructuredGraph graph = parse(methodName);
-                CanonicalizerPhase.Instance canonicalizerPhase = new CanonicalizerPhase.Instance(runtime, assumptions, true);
-                canonicalizerPhase.apply(graph);
+                PhaseContext context = new PhaseContext(runtime, assumptions, replacements);
+                CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
+                canonicalizer.apply(graph, context);
 
                 // Additional inlining.
                 final PhasePlan plan = new PhasePlan();
                 GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), TruffleCompilerImpl.Optimizations);
                 plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
-                plan.addPhase(PhasePosition.AFTER_PARSING, canonicalizerPhase);
+                canonicalizer.addToPhasePlan(plan, context);
                 plan.addPhase(PhasePosition.AFTER_PARSING, new DeadCodeEliminationPhase());
 
                 new ConvertDeoptimizeToGuardPhase().apply(graph);
-                canonicalizerPhase.apply(graph);
+                canonicalizer.apply(graph, context);
                 new DeadCodeEliminationPhase().apply(graph);
 
-                HighTierContext context = new HighTierContext(runtime, assumptions, replacements, null, plan, OptimisticOptimizations.NONE);
-                InliningPhase inliningPhase = new InliningPhase();
-                inliningPhase.apply(graph, context);
+                HighTierContext highTierContext = new HighTierContext(runtime, assumptions, replacements, null, plan, OptimisticOptimizations.NONE);
+                InliningPhase inliningPhase = new InliningPhase(canonicalizer);
+                inliningPhase.apply(graph, highTierContext);
                 removeFrameStates(graph);
 
                 new ConvertDeoptimizeToGuardPhase().apply(graph);
-                canonicalizerPhase.apply(graph);
+                canonicalizer.apply(graph, context);
                 new DeadCodeEliminationPhase().apply(graph);
 
-                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
-                canonicalizerPhase.apply(graph);
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context);
+                canonicalizer.apply(graph, context);
                 new DeadCodeEliminationPhase().apply(graph);
                 return graph;
             }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Tue Sep 10 16:33:28 2013 -0700
@@ -31,6 +31,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.hotspot.*;
@@ -42,6 +43,7 @@
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.common.*;
@@ -66,7 +68,7 @@
     private final MetaAccessProvider metaAccessProvider;
     private final ResolvedJavaType nodeClass;
     private final ResolvedJavaMethod executeHelperMethod;
-    private final CustomCanonicalizer customCanonicalizer;
+    private final CanonicalizerPhase canonicalizer;
     private final ResolvedJavaType[] skippedExceptionTypes;
     private final Replacements replacements;
     private Set<Constant> constantReceivers;
@@ -76,7 +78,8 @@
     public PartialEvaluator(MetaAccessProvider metaAccessProvider, Replacements replacements, TruffleCache truffleCache) {
         this.metaAccessProvider = metaAccessProvider;
         this.nodeClass = metaAccessProvider.lookupJavaType(com.oracle.truffle.api.nodes.Node.class);
-        this.customCanonicalizer = new PartialEvaluatorCanonicalizer(metaAccessProvider, nodeClass);
+        CustomCanonicalizer customCanonicalizer = new PartialEvaluatorCanonicalizer(metaAccessProvider, nodeClass);
+        this.canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue(), customCanonicalizer);
         this.skippedExceptionTypes = TruffleCompilerImpl.getSkippedExceptionTypes(metaAccessProvider);
         this.replacements = replacements;
         this.cache = HotSpotGraalRuntime.graalRuntime().getCache();
@@ -112,6 +115,7 @@
 
         Debug.scope("createGraph", graph, new Runnable() {
 
+            @SuppressWarnings("deprecation")
             @Override
             public void run() {
                 new GraphBuilderPhase(metaAccessProvider, config, TruffleCompilerImpl.Optimizations).apply(graph);
@@ -121,8 +125,8 @@
                 thisNode.replaceAndDelete(ConstantNode.forObject(node, metaAccessProvider, graph));
 
                 // Canonicalize / constant propagate.
-                CanonicalizerPhase.Instance canonicalizerPhase = new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, !AOTCompilation.getValue(), null, customCanonicalizer);
-                canonicalizerPhase.apply(graph);
+                PhaseContext baseContext = new PhaseContext(metaAccessProvider, assumptions, replacements);
+                canonicalizer.apply(graph, baseContext);
 
                 // Intrinsify methods.
                 new ReplaceIntrinsicsPhase(replacements).apply(graph);
@@ -147,29 +151,29 @@
                     for (Constant c : constantReceivers) {
                         histogram.add(c.asObject().getClass().getSimpleName());
                     }
-                    histogram.print(TTY.out().out());
+                    new DebugHistogramAsciiPrinter(TTY.out().out()).print(histogram);
                 }
 
                 // Additional inlining.
                 final PhasePlan plan = new PhasePlan();
                 GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(metaAccessProvider, config, TruffleCompilerImpl.Optimizations);
                 plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
-                plan.addPhase(PhasePosition.AFTER_PARSING, canonicalizerPhase);
+                canonicalizer.addToPhasePlan(plan, baseContext);
                 plan.addPhase(PhasePosition.AFTER_PARSING, new ReplaceIntrinsicsPhase(replacements));
 
                 new ConvertDeoptimizeToGuardPhase().apply(graph);
-                canonicalizerPhase.apply(graph);
+                canonicalizer.apply(graph, baseContext);
                 new DeadCodeEliminationPhase().apply(graph);
 
                 HighTierContext context = new HighTierContext(metaAccessProvider, assumptions, replacements, cache, plan, OptimisticOptimizations.NONE);
-                InliningPhase inliningPhase = new InliningPhase(customCanonicalizer);
+                InliningPhase inliningPhase = new InliningPhase(canonicalizer);
                 inliningPhase.apply(graph, context);
 
                 // Convert deopt to guards.
                 new ConvertDeoptimizeToGuardPhase().apply(graph);
 
                 // Canonicalize / constant propagate.
-                canonicalizerPhase.apply(graph);
+                canonicalizer.apply(graph, context);
 
                 for (NeverPartOfCompilationNode neverPartOfCompilationNode : graph.getNodes(NeverPartOfCompilationNode.class)) {
                     Throwable exception = new VerificationError(neverPartOfCompilationNode.getMessage());
@@ -178,21 +182,30 @@
 
                 // EA frame and clean up.
                 new VerifyFrameDoesNotEscapePhase().apply(graph, false);
-                new PartialEscapePhase(false).apply(graph, context);
+                new PartialEscapePhase(false, canonicalizer).apply(graph, context);
                 new VerifyNoIntrinsicsLeftPhase().apply(graph, false);
                 for (MaterializeFrameNode materializeNode : graph.getNodes(MaterializeFrameNode.class).snapshot()) {
                     materializeNode.replaceAtUsages(materializeNode.getFrame());
                     graph.removeFixed(materializeNode);
                 }
-                for (VirtualOnlyInstanceNode virtualOnlyNode : graph.getNodes(VirtualOnlyInstanceNode.class)) {
-                    virtualOnlyNode.setAllowMaterialization(true);
+                for (VirtualObjectNode virtualObjectNode : graph.getNodes(VirtualObjectNode.class)) {
+                    if (virtualObjectNode instanceof VirtualOnlyInstanceNode) {
+                        VirtualOnlyInstanceNode virtualOnlyInstanceNode = (VirtualOnlyInstanceNode) virtualObjectNode;
+                        virtualOnlyInstanceNode.setAllowMaterialization(true);
+                    } else if (virtualObjectNode instanceof VirtualInstanceNode) {
+                        VirtualInstanceNode virtualInstanceNode = (VirtualInstanceNode) virtualObjectNode;
+                        ResolvedJavaType type = virtualInstanceNode.type();
+                        if (type.getAnnotation(CompilerDirectives.ValueType.class) != null) {
+                            virtualInstanceNode.setIdentity(false);
+                        }
+                    }
                 }
 
                 // Convert deopt to guards.
                 new ConvertDeoptimizeToGuardPhase().apply(graph);
 
                 // Canonicalize / constant propagate.
-                canonicalizerPhase.apply(graph);
+                canonicalizer.apply(graph, context);
             }
         });
 
@@ -218,7 +231,7 @@
                         StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod());
                         NewFrameNode otherNewFrame = null;
                         if (inlineGraph == null) {
-                            inlineGraph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, !AOTCompilation.getValue());
+                            inlineGraph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions);
                             otherNewFrame = inlineGraph.getNodes(NewFrameNode.class).first();
                         }
 
@@ -246,7 +259,7 @@
         } while (changed && newFrameNode.isAlive() && newFrameNode.usages().isNotEmpty());
     }
 
-    private StructuredGraph parseGraph(final ResolvedJavaMethod targetMethod, final NodeInputList<ValueNode> arguments, final Assumptions assumptions, final boolean canonicalizeReads) {
+    private StructuredGraph parseGraph(final ResolvedJavaMethod targetMethod, final NodeInputList<ValueNode> arguments, final Assumptions assumptions) {
 
         final StructuredGraph graph = truffleCache.lookup(targetMethod, arguments, assumptions);
         Debug.scope("parseGraph", targetMethod, new Runnable() {
@@ -255,13 +268,14 @@
             public void run() {
 
                 // Canonicalize / constant propagate.
-                new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, canonicalizeReads, null, customCanonicalizer).apply(graph);
+                PhaseContext context = new PhaseContext(metaAccessProvider, assumptions, replacements);
+                canonicalizer.apply(graph, context);
 
                 // Intrinsify methods.
                 new ReplaceIntrinsicsPhase(replacements).apply(graph);
 
                 // Inline trivial getter methods
-                new InlineTrivialGettersPhase(metaAccessProvider, assumptions, customCanonicalizer).apply(graph);
+                new InlineTrivialGettersPhase(metaAccessProvider, canonicalizer).apply(graph, context);
 
                 // Convert deopt to guards.
                 new ConvertDeoptimizeToGuardPhase().apply(graph);
@@ -276,9 +290,9 @@
                             if (ex.counted().isConstantMaxTripCount()) {
                                 long constant = ex.counted().constantMaxTripCount();
                                 if (constant <= TruffleConstantUnrollLimit.getValue() || targetMethod.getAnnotation(ExplodeLoop.class) != null) {
-                                    LoopTransformations.fullUnroll(ex, metaAccessProvider, assumptions, canonicalizeReads);
+                                    LoopTransformations.fullUnroll(ex, context, canonicalizer);
                                     Debug.dump(graph, "After loop unrolling %d times", constant);
-                                    new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, canonicalizeReads, null, customCanonicalizer).apply(graph);
+                                    canonicalizer.apply(graph, context);
                                     unrolled = true;
                                     break;
                                 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Tue Sep 10 16:33:28 2013 -0700
@@ -112,7 +112,7 @@
                     optimizeGraph(newGraph, tmpAssumptions);
 
                     PhaseContext context = new PhaseContext(metaAccessProvider, tmpAssumptions, replacements);
-                    PartialEscapePhase partialEscapePhase = new PartialEscapePhase(false);
+                    PartialEscapePhase partialEscapePhase = new PartialEscapePhase(false, new CanonicalizerPhase(!AOTCompilation.getValue()));
                     partialEscapePhase.apply(newGraph, context);
 
                     cache.put(method, newGraph);
@@ -153,7 +153,7 @@
         ConditionalEliminationPhase conditionalEliminationPhase = new ConditionalEliminationPhase(metaAccessProvider);
         ConvertDeoptimizeToGuardPhase convertDeoptimizeToGuardPhase = new ConvertDeoptimizeToGuardPhase();
         CanonicalizerPhase canonicalizerPhase = new CanonicalizerPhase(!AOTCompilation.getValue());
-        EarlyReadEliminationPhase readEliminationPhase = new EarlyReadEliminationPhase();
+        EarlyReadEliminationPhase readEliminationPhase = new EarlyReadEliminationPhase(canonicalizerPhase);
 
         int maxNodes = TruffleCompilerOptions.TruffleOperationCacheMaxNodes.getValue();
 
@@ -205,6 +205,10 @@
     }
 
     private void expandPath(StructuredGraph newGraph, int maxNodes, NodeBitMap visitedNodes, AbstractBeginNode start, Queue<AbstractBeginNode> workQueue) {
+        if (start.isDeleted()) {
+            return;
+        }
+
         FixedNode next = start;
         while (!visitedNodes.isMarked(next)) {
             visitedNodes.mark(next);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Tue Sep 10 16:33:28 2013 -0700
@@ -23,7 +23,6 @@
 package com.oracle.graal.truffle;
 
 import static com.oracle.graal.api.code.CodeUtil.*;
-import static com.oracle.graal.compiler.GraalDebugConfig.*;
 
 import java.util.*;
 import java.util.concurrent.*;
@@ -36,6 +35,7 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
@@ -83,7 +83,7 @@
 
         this.partialEvaluator = new PartialEvaluator(metaAccessProvider, replacements, truffleCache);
 
-        if (DebugEnabled.getValue()) {
+        if (Debug.isEnabled()) {
             DebugEnvironment.initialize(System.out);
         }
     }
@@ -107,6 +107,10 @@
         });
     }
 
+    public static final DebugTimer PartialEvaluationTime = Debug.timer("PartialEvaluationTime");
+    public static final DebugTimer CompilationTime = Debug.timer("CompilationTime");
+    public static final DebugTimer CodeInstallationTime = Debug.timer("CodeInstallation");
+
     private InstalledCode compileMethodImpl(final OptimizedCallTarget compilable) {
         final StructuredGraph graph;
         final GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault();
@@ -115,7 +119,9 @@
 
         compilable.timeCompilationStarted = System.nanoTime();
         Assumptions assumptions = new Assumptions(true);
-        graph = partialEvaluator.createGraph(compilable, assumptions);
+        try (TimerCloseable a = PartialEvaluationTime.start()) {
+            graph = partialEvaluator.createGraph(compilable, assumptions);
+        }
         compilable.timePartialEvaluationFinished = System.nanoTime();
         compilable.nodeCountPartialEval = graph.getNodeCount();
         InstalledCode compiledMethod = compileMethodHelper(graph, config, compilable, assumptions);
@@ -143,9 +149,11 @@
 
             @Override
             public CompilationResult call() {
-                CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
-                return GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, replacements, backend, runtime.getTarget(), null, plan, OptimisticOptimizations.ALL, new SpeculationLog(),
-                                suites, new CompilationResult());
+                try (TimerCloseable a = CompilationTime.start()) {
+                    CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+                    return GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, replacements, backend, runtime.getTarget(), null, plan, OptimisticOptimizations.ALL, new SpeculationLog(),
+                                    suites, new CompilationResult());
+                }
             }
         });
 
@@ -169,11 +177,13 @@
 
             @Override
             public InstalledCode call() throws Exception {
-                InstalledCode installedCode = runtime.addMethod(graph.method(), result);
-                if (installedCode != null) {
-                    Debug.dump(new Object[]{result, installedCode}, "After code installation");
+                try (TimerCloseable a = CodeInstallationTime.start()) {
+                    InstalledCode installedCode = runtime.addMethod(graph.method(), result);
+                    if (installedCode != null) {
+                        Debug.dump(new Object[]{result, installedCode}, "After code installation");
+                    }
+                    return installedCode;
                 }
-                return installedCode;
             }
         });
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -77,7 +77,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         IntegerExactArithmeticSplitNode.lower(tool, this);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -29,7 +29,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.spi.Lowerable.*;
 import com.oracle.graal.nodes.type.*;
 
 public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRGenLowerable {
@@ -82,7 +81,7 @@
     protected abstract Value generateArithmetic(LIRGeneratorTool generator);
 
     static void lower(LoweringTool tool, IntegerExactArithmeticNode node) {
-        if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+        if (node.asNode().graph().getGuardsPhase() == StructuredGraph.GuardsPhase.FIXED_DEOPTS) {
             FloatingNode floatingNode = (FloatingNode) node;
             FixedWithNextNode previous = tool.lastFixedNode();
             FixedNode next = previous.next();
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -73,7 +73,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         IntegerExactArithmeticSplitNode.lower(tool, this);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -77,7 +77,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         IntegerExactArithmeticSplitNode.lower(tool, this);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -33,7 +33,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         InvokeNode invoke = createInvoke();
         graph().replaceFixedWithFixed(this, invoke);
         invoke.setUseForInlining(false);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameGetNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameGetNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -25,7 +25,6 @@
 import sun.misc.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.Node.IterableNodeType;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
@@ -40,7 +39,7 @@
  * Intrinsic node for read access to a Truffle frame.
  */
 @NodeInfo(nameTemplate = "FrameGet{p#slotKind/s}{p#frameSlot/s}")
-public class FrameGetNode extends FrameAccessNode implements IterableNodeType, Virtualizable, Lowerable {
+public class FrameGetNode extends FrameAccessNode implements Node.IterableNodeType, Virtualizable, Lowerable {
 
     public FrameGetNode(Kind kind, ValueNode frame, ValueNode slot, ResolvedJavaField field) {
         super(StampFactory.forKind(kind), kind, frame, slot, field);
@@ -71,7 +70,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         assert !(getFrame() instanceof NewFrameNode);
         StructuredGraph structuredGraph = graph();
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameSetNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameSetNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -23,7 +23,6 @@
 package com.oracle.graal.truffle.nodes.frame;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.Node.IterableNodeType;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
@@ -37,7 +36,7 @@
  * Intrinsic node for write access to a Truffle frame.
  */
 @NodeInfo(nameTemplate = "FrameSet{p#slotKind/s}{p#frameSlot/s}")
-public class FrameSetNode extends FrameAccessNode implements IterableNodeType, Virtualizable, Lowerable {
+public class FrameSetNode extends FrameAccessNode implements Node.IterableNodeType, Virtualizable, Lowerable {
 
     @Input private ValueNode value;
 
@@ -71,7 +70,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool, LoweringType loweringType) {
+    public void lower(LoweringTool tool) {
         assert !(getFrame() instanceof NewFrameNode);
         StructuredGraph structuredGraph = graph();
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.truffle.nodes.frame;
 
-import com.oracle.graal.graph.Node.IterableNodeType;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.truffle.*;
@@ -31,7 +30,7 @@
  * Intrinsic node for materializing a Truffle frame.
  */
 @NodeInfo(nameTemplate = "MaterializeFrame{p#frame/s}")
-public class MaterializeFrameNode extends FixedWithNextNode implements IterableNodeType {
+public class MaterializeFrameNode extends FixedWithNextNode implements Node.IterableNodeType {
 
     @Input private ValueNode frame;
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -27,7 +27,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.IterableNodeType;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -43,7 +42,7 @@
  * Intrinsic node representing the call for creating a frame in the {@link OptimizedCallTarget}
  * class.
  */
-public class NewFrameNode extends FixedWithNextNode implements IterableNodeType, VirtualizableAllocation, Canonicalizable {
+public class NewFrameNode extends FixedWithNextNode implements Node.IterableNodeType, VirtualizableAllocation, Canonicalizable {
 
     static final ResolvedJavaType FRAME_TYPE = Graal.getRequiredCapability(MetaAccessProvider.class).lookupJavaType(FrameWithoutBoxing.class);
 
@@ -92,12 +91,12 @@
         throw new RuntimeException("Frame field not found: " + fieldName);
     }
 
-    public static class VirtualOnlyInstanceNode extends VirtualInstanceNode implements Node.IterableNodeType {
+    public static class VirtualOnlyInstanceNode extends VirtualInstanceNode {
 
         private boolean allowMaterialization;
 
         public VirtualOnlyInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) {
-            super(type, fields);
+            super(type, fields, false);
         }
 
         @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomTypeCheckNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomTypeCheckNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -50,8 +50,8 @@
         return customType;
     }
 
-    public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.BEFORE_GUARDS) {
+    public void lower(LoweringTool tool) {
+        if (graph().getGuardsPhase() == StructuredGraph.GuardsPhase.FLOATING_GUARDS) {
             this.replaceAtUsages(graph().unique(new IntegerEqualsNode(condition, ConstantNode.forInt(1, graph()))));
             this.safeDelete();
         }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -59,8 +59,8 @@
         return customType;
     }
 
-    public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.BEFORE_GUARDS) {
+    public void lower(LoweringTool tool) {
+        if (graph().getGuardsPhase() == StructuredGraph.GuardsPhase.FLOATING_GUARDS) {
             ValueAnchorNode valueAnchorNode = graph().add(new ValueAnchorNode());
             UnsafeCastNode unsafeCast = graph().unique(new UnsafeCastNode(object, this.stamp(), (GuardingNode) valueAnchorNode));
             this.replaceAtUsages(unsafeCast);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/InlineTrivialGettersPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/InlineTrivialGettersPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,9 +22,6 @@
  */
 package com.oracle.graal.truffle.phases;
 
-import static com.oracle.graal.phases.GraalOptions.*;
-
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.java.*;
@@ -33,27 +30,25 @@
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.truffle.*;
 
 /**
  * Inline all trivial getters (i.e. simple field loads).
  */
-public class InlineTrivialGettersPhase extends Phase {
+public class InlineTrivialGettersPhase extends BasePhase<PhaseContext> {
 
     private static final int TRIVIAL_GETTER_SIZE = 5;
     private final MetaAccessProvider metaAccessProvider;
-    private final Assumptions assumptions;
-    private final CustomCanonicalizer customCanonicalizer;
+    private final CanonicalizerPhase canonicalizer;
 
-    public InlineTrivialGettersPhase(MetaAccessProvider metaAccessProvider, Assumptions assumptions, CustomCanonicalizer customCanonicalizer) {
+    public InlineTrivialGettersPhase(MetaAccessProvider metaAccessProvider, CanonicalizerPhase canonicalizer) {
         this.metaAccessProvider = metaAccessProvider;
-        this.assumptions = assumptions;
-        this.customCanonicalizer = customCanonicalizer;
+        this.canonicalizer = canonicalizer;
     }
 
     @Override
-    protected void run(StructuredGraph graph) {
+    protected void run(StructuredGraph graph, PhaseContext context) {
         for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) {
             if (methodCallTarget.isAlive()) {
                 InvokeKind invokeKind = methodCallTarget.invokeKind();
@@ -66,7 +61,7 @@
                             int mark = graph.getMark();
                             InliningUtil.inline(methodCallTarget.invoke(), inlineGraph, false);
                             Debug.dump(graph, "After inlining trivial getter %s", targetMethod.toString());
-                            new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, !AOTCompilation.getValue(), mark, customCanonicalizer).apply(graph);
+                            canonicalizer.applyIncremental(graph, context, mark);
                         }
                     }
                 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyNoIntrinsicsLeftPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyNoIntrinsicsLeftPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -23,7 +23,6 @@
 package com.oracle.graal.truffle.phases;
 
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.IterableNodeType;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.truffle.*;
@@ -40,7 +39,7 @@
         verifyNoInstanceLeft(graph, NewFrameNode.class);
     }
 
-    public static <T extends Node & IterableNodeType> void verifyNoInstanceLeft(StructuredGraph graph, Class<T> clazz) {
+    public static <T extends Node & Node.IterableNodeType> void verifyNoInstanceLeft(StructuredGraph graph, Class<T> clazz) {
         if (graph.getNodes(clazz).count() != 0) {
             throw new VerificationError("Found unexpected node(s): %s", graph.getNodes(clazz));
         }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -25,13 +25,14 @@
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.phases.tiers.*;
 
 public class EarlyReadEliminationPhase extends EffectsPhase<PhaseContext> {
 
-    public EarlyReadEliminationPhase() {
-        super(1);
+    public EarlyReadEliminationPhase(CanonicalizerPhase canonicalizer) {
+        super(1, canonicalizer);
     }
 
     @Override
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.virtual.phases.ea;
 
-import static com.oracle.graal.phases.GraalOptions.*;
-
 import java.util.concurrent.*;
 
 import com.oracle.graal.debug.*;
@@ -47,9 +45,11 @@
     }
 
     private final int maxIterations;
+    private final CanonicalizerPhase canonicalizer;
 
-    public EffectsPhase(int maxIterations) {
+    public EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer) {
         this.maxIterations = maxIterations;
+        this.canonicalizer = canonicalizer;
     }
 
     @Override
@@ -90,7 +90,7 @@
                             listener.getChangedNodes().add(node);
                         }
                     }
-                    new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), !AOTCompilation.getValue(), listener.getChangedNodes(), null).apply(graph);
+                    canonicalizer.applyIncremental(graph, context, listener.getChangedNodes());
 
                     return true;
                 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -60,13 +60,13 @@
                 @Override
                 public Boolean call() {
                     boolean progress = false;
-                    PartialEscapePhase ea = new PartialEscapePhase(false);
+                    PartialEscapePhase ea = new PartialEscapePhase(false, canonicalizer);
                     boolean eaResult = ea.runAnalysis(graph, context);
                     progress |= eaResult;
 
                     Map<Invoke, Double> hints = PEAInliningHints.getValue() ? PartialEscapePhase.getHints(graph) : null;
 
-                    InliningPhase inlining = new InliningPhase(hints);
+                    InliningPhase inlining = new InliningPhase(hints, new CanonicalizerPhase(true));
                     inlining.setMaxMethodsPerInlining(simple ? 1 : Integer.MAX_VALUE);
                     inlining.apply(graph, context);
                     progress |= inlining.getInliningCount() > 0;
@@ -75,7 +75,7 @@
 
                     if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
                         canonicalizer.apply(graph, context);
-                        new IterativeConditionalEliminationPhase().apply(graph, context);
+                        new IterativeConditionalEliminationPhase(canonicalizer).apply(graph, context);
                     }
 
                     return progress;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Tue Sep 10 16:33:28 2013 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.virtual.phases.ea;
 
 import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.virtual.phases.ea.PartialEscapePhase.Options.*;
 
 import java.util.*;
 
@@ -33,25 +34,29 @@
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.options.*;
+import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.phases.tiers.*;
 
 public class PartialEscapePhase extends EffectsPhase<PhaseContext> {
 
-    //@formatter:off
-    @Option(help = "")
-    public static final OptionValue<Boolean> OptEarlyReadElimination = new OptionValue<>(true);
-    //@formatter:on
+    static class Options {
+
+        //@formatter:off
+        @Option(help = "")
+        public static final OptionValue<Boolean> OptEarlyReadElimination = new OptionValue<>(true);
+        //@formatter:on
+    }
 
     private final boolean readElimination;
 
-    public PartialEscapePhase(boolean iterative) {
-        this(iterative, OptEarlyReadElimination.getValue());
+    public PartialEscapePhase(boolean iterative, CanonicalizerPhase canonicalizer) {
+        this(iterative, OptEarlyReadElimination.getValue(), canonicalizer);
     }
 
-    public PartialEscapePhase(boolean iterative, boolean readElimination) {
-        super(iterative ? EscapeAnalysisIterations.getValue() : 1);
+    public PartialEscapePhase(boolean iterative, boolean readElimination, CanonicalizerPhase canonicalizer) {
+        super(iterative ? EscapeAnalysisIterations.getValue() : 1, canonicalizer);
         this.readElimination = readElimination;
     }
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Tue Sep 10 16:33:28 2013 -0700
@@ -67,9 +67,6 @@
         }
 
         for (Node node : graph.getNodes()) {
-            if (node instanceof LocalNode) {
-                flood.add(node);
-            }
             if (flood.isMarked(node)) {
                 for (Node input : node.inputs()) {
                     flood.add(input);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CompilerErrorTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -0,0 +1,57 @@
+/*
+ * 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.truffle.api.dsl.test;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class CompilerErrorTest {
+
+    abstract static class Visiblity01 extends ValueNode {
+
+        @Specialization
+        @SuppressWarnings("static-method")
+        @ExpectError("Method annotated with @Specialization must not be private.")
+        private Object s() {
+            return null;
+        }
+
+    }
+
+    @ExpectError("Classes containing a @Specialization annotation must not be private.")
+    private abstract static class Visiblity02 extends ValueNode {
+
+        @Specialization
+        public Object s() {
+            return null;
+        }
+
+    }
+
+    // assert no error
+    @ExpectError({})
+    private abstract static class Visiblity03 extends ValueNode {
+
+    }
+
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -34,11 +34,15 @@
 import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithBoxedPrimitiveFactory;
 import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithObjectFactory;
 import com.oracle.truffle.api.dsl.test.GuardsTestFactory.InvocationGuardFactory;
+import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestAbstractGuard1Factory;
 import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve1Factory;
 import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve2Factory;
 import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve3Factory;
 import com.oracle.truffle.api.dsl.test.NodeContainerTest.Str;
 import com.oracle.truffle.api.dsl.test.NodeContainerTest.StrBase;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.Abstract;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.BExtendsAbstract;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.CExtendsAbstract;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
 
@@ -271,4 +275,43 @@
         }
     }
 
+    @NodeChild("expression")
+    public abstract static class TestGuardResolve4 extends ValueNode {
+
+        boolean guard(StrBase primitive) {
+            return false;
+        }
+
+        @Specialization(guards = "guard")
+        int doSpecialized(Str value0) {
+            return 42;
+        }
+    }
+
+    @Test
+    public void testAbstractGuard1() {
+        TestRootNode<?> root = createRoot(TestAbstractGuard1Factory.getInstance());
+
+        assertEquals(BExtendsAbstract.INSTANCE, executeWith(root, BExtendsAbstract.INSTANCE));
+        assertEquals(CExtendsAbstract.INSTANCE, executeWith(root, CExtendsAbstract.INSTANCE));
+    }
+
+    @NodeChild("expression")
+    public abstract static class TestAbstractGuard1 extends ValueNode {
+
+        boolean guard(Abstract value0) {
+            return true;
+        }
+
+        @Specialization(order = 1, guards = "guard")
+        BExtendsAbstract doSpecialized1(BExtendsAbstract value0) {
+            return value0;
+        }
+
+        @Specialization(order = 2, guards = "guard")
+        CExtendsAbstract doSpecialized2(CExtendsAbstract value0) {
+            return value0;
+        }
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2012, 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.truffle.api.dsl.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast0NodeFactory;
+import com.oracle.truffle.api.dsl.test.NodeContainerTest.Str;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.frame.*;
+
+public class ImplicitCastTest {
+
+    @TypeSystem({int.class, boolean.class, String.class, Str.class})
+    static class ImplicitCast0Types {
+
+        @ImplicitCast
+        boolean castInt(int intvalue) {
+            return intvalue == 1 ? true : false;
+        }
+
+        @ImplicitCast
+        boolean castString(String strvalue) {
+            return strvalue.equals("1");
+        }
+
+    }
+
+    @TypeSystemReference(ImplicitCast0Types.class)
+    @NodeChild(value = "operand", type = ImplicitCast0Node.class)
+    abstract static class ImplicitCast0Node extends ValueNode {
+
+        public abstract Object executeEvaluated(VirtualFrame frame, Object value2);
+
+        @Specialization(order = 1)
+        public String op1(String value) throws RuntimeException {
+            return value;
+        }
+
+        @Specialization(order = 2)
+        public boolean op1(boolean value) throws RuntimeException {
+            return value;
+        }
+
+    }
+
+    @Test
+    public void testImplicitCast0() {
+        ImplicitCast0Node node = ImplicitCast0NodeFactory.create(null);
+        TestRootNode<ImplicitCast0Node> root = new TestRootNode<>(node);
+        Assert.assertEquals("2", root.getNode().executeEvaluated(null, "2"));
+        Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1));
+        Assert.assertEquals("1", root.getNode().executeEvaluated(null, "1"));
+        Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1));
+        Assert.assertEquals(true, root.getNode().executeEvaluated(null, true));
+    }
+
+    // TODO assert implicit casts only in one direction
+
+    // test example that covers the most cases
+
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -146,4 +146,21 @@
 
     }
 
+    @Test
+    public void testObjectContainer() {
+        assertEquals("42", createCallTarget(ObjectContainerNodeFactory.create("42")).call());
+    }
+
+    @NodeField(name = "object", type = Object.class)
+    abstract static class ObjectContainerNode extends ValueNode {
+
+        public abstract Object getObject();
+
+        @Specialization
+        Object containerField() {
+            return getObject();
+        }
+
+    }
+
 }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -37,6 +37,17 @@
 
 public class PolymorphicTest {
 
+    private static void assertParent(Node expectedParent, Node child) {
+        Node parent = child.getParent();
+        while (parent != null && parent != expectedParent) {
+            parent = parent.getParent();
+        }
+
+        if (parent != expectedParent) {
+            assertEquals(expectedParent, parent);
+        }
+    }
+
     @Test
     public void testJustSpecialize() {
         TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
@@ -45,8 +56,8 @@
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(boolean,int)", executeWith(node, false, 42));
         assertEquals(Kind.SPECIALIZED, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
-        assertEquals(node.getNode(), node.getNode().getLeft().getParent());
-        assertEquals(node.getNode(), node.getNode().getRight().getParent());
+        assertParent(node.getNode(), node.getNode().getLeft());
+        assertParent(node.getNode(), node.getNode().getRight());
     }
 
     @Test
@@ -55,8 +66,8 @@
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
         assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
-        assertEquals(node.getNode(), node.getNode().getLeft().getParent());
-        assertEquals(node.getNode(), node.getNode().getRight().getParent());
+        assertParent(node.getNode(), node.getNode().getLeft());
+        assertParent(node.getNode(), node.getNode().getRight());
     }
 
     @Test
@@ -66,8 +77,8 @@
         assertEquals("(boolean,boolean)", executeWith(node, true, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
         assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
-        assertEquals(node.getNode(), node.getNode().getLeft().getParent());
-        assertEquals(node.getNode(), node.getNode().getRight().getParent());
+        assertParent(node.getNode(), node.getNode().getLeft());
+        assertParent(node.getNode(), node.getNode().getRight());
     }
 
     @Test
@@ -78,17 +89,17 @@
         assertEquals("(boolean,boolean)", executeWith(node, true, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
         assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
-        assertEquals(node.getNode(), node.getNode().getLeft().getParent());
-        assertEquals(node.getNode(), node.getNode().getRight().getParent());
+        assertParent(node.getNode(), node.getNode().getLeft());
+        assertParent(node.getNode(), node.getNode().getRight());
     }
 
     @Test
     public void testGenericInitial() {
         TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
-        assertEquals("(generic,generic)", executeWith(node, "", ""));
+        assertEquals("(generic,generic)", executeWith(node, "1", "1"));
         assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
-        assertEquals(node.getNode(), node.getNode().getLeft().getParent());
-        assertEquals(node.getNode(), node.getNode().getRight().getParent());
+        assertParent(node.getNode(), node.getNode().getLeft());
+        assertParent(node.getNode(), node.getNode().getRight());
     }
 
     @Test
@@ -99,8 +110,8 @@
         assertEquals("(generic,generic)", executeWith(node, "", ""));
         assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
         /* Assertions for bug GRAAL-425 */
-        assertEquals(node.getNode(), node.getNode().getLeft().getParent());
-        assertEquals(node.getNode(), node.getNode().getRight().getParent());
+        assertParent(node.getNode(), node.getNode().getLeft());
+        assertParent(node.getNode(), node.getNode().getRight());
     }
 
     @SuppressWarnings("unused")
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -26,10 +26,13 @@
 
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.SpecializationGroupingTestFactory.TestElseConnectionBug1Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationGroupingTestFactory.TestElseConnectionBug2Factory;
 import com.oracle.truffle.api.dsl.test.SpecializationGroupingTestFactory.TestGroupingFactory;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.SimpleTypes;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 
 /**
@@ -154,6 +157,83 @@
 
     }
 
+    @Test
+    public void testElseConnectionBug1() {
+        CallTarget target = TestHelper.createCallTarget(TestElseConnectionBug1Factory.create(new GenericInt()));
+        Assert.assertEquals(42, target.call());
+    }
+
+    @SuppressWarnings("unused")
+    @NodeChild(value = "genericChild", type = GenericInt.class)
+    public abstract static class TestElseConnectionBug1 extends ValueNode {
+
+        @Specialization(order = 1, rewriteOn = {SlowPathException.class}, guards = "isInitialized")
+        public int doInteger(int value) throws SlowPathException {
+            throw new SlowPathException();
+        }
+
+        @Specialization(order = 3, guards = "isInitialized")
+        public int doObject(int value) {
+            return value == 42 ? value : 0;
+        }
+
+        @Specialization(order = 4, guards = "!isInitialized")
+        public Object doUninitialized(int value) {
+            throw new AssertionError();
+        }
+
+        boolean isInitialized(int value) {
+            return true;
+        }
+    }
+
+    public static final class GenericInt extends ValueNode {
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return executeInt(frame);
+        }
+
+        @Override
+        public int executeInt(VirtualFrame frame) {
+            return 42;
+        }
+
+    }
+
+    @Test
+    public void testElseConnectionBug2() {
+        TestHelper.assertRuns(TestElseConnectionBug2Factory.getInstance(), 42, 42);
+    }
+
+    @SuppressWarnings("unused")
+    @NodeChild
+    public abstract static class TestElseConnectionBug2 extends ValueNode {
+
+        @Specialization(order = 2, guards = "guard0")
+        public int doGuard0(int value) {
+            throw new AssertionError();
+        }
+
+        @Specialization(order = 3, guards = "guard1")
+        public int doGuard1(int value) {
+            throw new AssertionError();
+        }
+
+        @Specialization(order = 4, guards = "!guard0")
+        public int doUninitialized(int value) {
+            return value;
+        }
+
+        boolean guard0(int value) {
+            return false;
+        }
+
+        boolean guard1(int value) {
+            return false;
+        }
+    }
+
     private static class MockAssumption implements Assumption {
 
         int checked;
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java	Tue Sep 10 16:33:28 2013 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.api.dsl.test;
 
+import static org.junit.Assert.*;
+
 import java.util.*;
 
 import com.oracle.truffle.api.*;
@@ -75,4 +77,69 @@
         return createCallTarget(node).call(new TestArguments(values));
     }
 
+    static Object array(Object... val) {
+        return val;
+    }
+
+    static <E> List<List<E>> permutations(List<E> list) {
+        return permutations(new ArrayList<E>(), list, new ArrayList<List<E>>());
+    }
+
+    static Object[][] permutations(Object... list) {
+        List<List<Object>> permutations = permutations(Arrays.asList(list));
+
+        Object[][] a = new Object[permutations.size()][];
+        int index = 0;
+        for (List<Object> p : permutations) {
+            a[index] = p.toArray(new Object[p.size()]);
+            index++;
+        }
+
+        return a;
+    }
+
+    static <E> List<List<E>> permutations(List<E> prefix, List<E> suffix, List<List<E>> output) {
+        if (suffix.size() == 1) {
+            ArrayList<E> newElement = new ArrayList<>(prefix);
+            newElement.addAll(suffix);
+            output.add(newElement);
+            return output;
+        }
+
+        for (int i = 0; i < suffix.size(); i++) {
+            List<E> newPrefix = new ArrayList<>(prefix);
+            newPrefix.add(suffix.get(i));
+            List<E> newSuffix = new ArrayList<>(suffix);
+            newSuffix.remove(i);
+            permutations(newPrefix, newSuffix, output);
+        }
+
+        return output;
+    }
+
+    /* Methods tests all test values in combinational order. */
+    static void assertRuns(NodeFactory<? extends ValueNode> factory, Object result, Object... testValues) {
+        // test each run by its own.
+        for (int i = 0; i < testValues.length; i++) {
+            assertValue(createRoot(factory), result, testValues);
+        }
+
+        // test all combinations of the test values
+        List<List<Object>> permuts = permutations(Arrays.asList(testValues));
+        for (List<Object> list : permuts) {
+            TestRootNode<?> root = createRoot(factory);
+            for (Object object : list) {
+                assertValue(root, result, object);
+            }
+        }
+    }
+
+    static void assertValue(TestRootNode<? extends ValueNode> root, Object result, Object testValues) {
+        if (testValues instanceof Object[]) {
+            assertEquals(result, executeWith(root, (Object[]) testValues));
+        } else {
+            assertEquals(result, executeWith(root, testValues));
+        }
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemErrorsTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012, 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.truffle.api.dsl.test;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.*;
+
+public class TypeSystemErrorsTest {
+
+    @TypeSystem({int.class, boolean.class})
+    public static class Types0 {
+
+    }
+
+    @ExpectError("Invalid type order. The type(s) [java.lang.String] are inherited from a earlier defined type java.lang.CharSequence.")
+    @TypeSystem({CharSequence.class, String.class})
+    public static class Types1 {
+
+    }
+
+    @TypeSystem({int.class, boolean.class})
+    public static class Types2 {
+
+        @TypeCast
+        @ExpectError("The provided return type \"String\" does not match expected return type \"int\".%")
+        String asInteger(Object value) {
+            return (String) value;
+        }
+
+    }
+
+    @TypeSystem({int.class, boolean.class})
+    public static class Types3 {
+
+        @TypeCast
+        @ExpectError("The provided return type \"boolean\" does not match expected return type \"int\".%")
+        boolean asInteger(Object value) {
+            return (boolean) value;
+        }
+
+    }
+
+    @TypeSystemReference(Types0.class)
+    @NodeChild
+    @ExpectError("The @TypeSystem of the node and the @TypeSystem of the @NodeChild does not match. Types0 != SimpleTypes. ")
+    abstract static class ErrorNode1 extends ValueNode {
+
+    }
+
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Tue Sep 10 16:33:28 2013 -0700
@@ -30,7 +30,7 @@
 
 public class TypeSystemTest {
 
-    @TypeSystem({int.class, boolean.class, String.class, Str.class, CallTarget.class, Object[].class})
+    @TypeSystem({int.class, boolean.class, String.class, Str.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class, Abstract.class, Object[].class})
     static class SimpleTypes {
 
         static int intCheck;
@@ -48,6 +48,11 @@
             return (int) value;
         }
 
+        @ImplicitCast
+        Str castStr(String strvalue) {
+            return new Str(strvalue);
+        }
+
     }
 
     @TypeSystemReference(SimpleTypes.class)
@@ -73,6 +78,14 @@
             return SimpleTypesGen.SIMPLETYPES.expectObjectArray(execute(frame));
         }
 
+        public BExtendsAbstract executeBExtendsAbstract(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.SIMPLETYPES.expectBExtendsAbstract(execute(frame));
+        }
+
+        public CExtendsAbstract executeCExtendsAbstract(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.SIMPLETYPES.expectCExtendsAbstract(execute(frame));
+        }
+
         public abstract Object execute(VirtualFrame frame);
 
         @Override
@@ -154,4 +167,18 @@
 
     }
 
+    abstract static class Abstract {
+    }
+
+    static final class BExtendsAbstract extends Abstract {
+
+        static final BExtendsAbstract INSTANCE = new BExtendsAbstract();
+
+    }
+
+    static final class CExtendsAbstract extends Abstract {
+
+        static final CExtendsAbstract INSTANCE = new CExtendsAbstract();
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ExpectError.java	Tue Sep 10 16:33:28 2013 -0700
@@ -0,0 +1,38 @@
+/*
+ * 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.  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.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is internally known by the dsl processor and used to expect errors for testing
+ * purposes. This is not part of public API.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ExpectError {
+
+    String[] value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImplicitCast.java	Tue Sep 10 16:33:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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.  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.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+/**
+ * EXPERIMENTAL Filter feature. May change or disappear without notice. This feature is not
+ * functional yet.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface ImplicitCast {
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Tue Sep 10 16:33:28 2013 -0700
@@ -205,4 +205,13 @@
     @Target({ElementType.METHOD})
     public @interface SlowPath {
     }
+
+    /**
+     * Marks classes as value types. Reference comparisons (==) between instances of those classes
+     * have undefined semantics and can either return true or false.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.TYPE})
+    public @interface ValueType {
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Tue Sep 10 16:33:28 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -59,6 +59,11 @@
         CompilerAsserts.neverPartOfCompilation();
     }
 
+    protected Node(SourceSection sourceSection) {
+        CompilerAsserts.neverPartOfCompilation();
+        this.sourceSection = sourceSection;
+    }
+
     /**
      * Assigns a link to a guest language source section to this node.
      * 
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Tue Sep 10 16:33:28 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -34,6 +34,13 @@
  */
 public abstract class RootNode extends Node {
 
+    protected RootNode() {
+    }
+
+    protected RootNode(SourceSection sourceSection) {
+        super(sourceSection);
+    }
+
     /**
      * Executes this function using the specified frame and returns the result value.
      * 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java	Tue Sep 10 16:33:28 2013 -0700
@@ -65,7 +65,7 @@
                 return null;
             }
 
-            model.emitMessages((TypeElement) element, log);
+            model.emitMessages(context, (TypeElement) element, log);
             return filterErrorElements(model);
         } catch (CompileErrorException e) {
             log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage());
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java	Tue Sep 10 16:33:28 2013 -0700
@@ -96,7 +96,7 @@
 
     private static void handleThrowable(AnnotationProcessor generator, Throwable t, Element e) {
         String message = "Uncaught error in " + generator.getClass().getSimpleName() + " while processing " + e;
-        generator.getContext().getLog().message(Kind.ERROR, e, null, null, message + ": " + Utils.printException(t));
+        generator.getContext().getEnvironment().getMessager().printMessage(Kind.ERROR, message + ": " + Utils.printException(t), e);
     }
 
     @SuppressWarnings("unchecked")
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Tue Sep 10 16:33:28 2013 -0700
@@ -30,6 +30,7 @@
 
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.CompilerDirectives.*;
+import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.nodes.Node.Child;
@@ -56,6 +57,7 @@
     private final TypeMirror compilerAsserts;
     private final DeclaredType slowPath;
     private final DeclaredType truffleOptions;
+    private final TypeElement expectError;
 
     private final List<String> errors = new ArrayList<>();
 
@@ -74,6 +76,11 @@
         nodeInfoKind = getRequired(context, NodeInfo.Kind.class);
         slowPath = getRequired(context, SlowPath.class);
         truffleOptions = getRequired(context, TruffleOptions.class);
+        expectError = (TypeElement) getRequired(context, ExpectError.class).asElement();
+    }
+
+    public TypeElement getExpectError() {
+        return expectError;
     }
 
     public DeclaredType getNodeInfoAnnotation() {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java	Tue Sep 10 16:33:28 2013 -0700
@@ -192,6 +192,10 @@
             return true;
         }
 
+        if (isObject(to)) {
+            return true;
+        }
+
         // JLS 5.1.2 widening primitives
         if (Utils.isPrimitive(from) && Utils.isPrimitive(to)) {
             TypeKind fromKind = from.getKind();
@@ -257,6 +261,10 @@
             return isAssignable(context, ((ArrayType) from).getComponentType(), ((ArrayType) to).getComponentType());
         }
 
+        if (from instanceof ArrayType || to instanceof ArrayType) {
+            return false;
+        }
+
         TypeElement fromType = Utils.fromTypeMirror(from);
         TypeElement toType = Utils.fromTypeMirror(to);
         if (fromType == null || toType == null) {
@@ -423,6 +431,8 @@
                 return getSimpleName(mirror);
             case ERROR:
                 throw new CompileErrorException("Type error " + mirror);
+            case EXECUTABLE:
+                return ((ExecutableType) mirror).toString();
             case NONE:
                 return "$none";
             default:
@@ -755,6 +765,10 @@
 
     public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List<? extends AnnotationMirror> mirrors, Class<?> annotationClass) {
         TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName());
+        return findAnnotationMirror(mirrors, expectedAnnotationType);
+    }
+
+    public static AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> mirrors, TypeElement expectedAnnotationType) {
         for (AnnotationMirror mirror : mirrors) {
             DeclaredType annotationType = mirror.getAnnotationType();
             TypeElement actualAnnotationType = (TypeElement) annotationType.asElement();
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeBuilder.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeBuilder.java	Tue Sep 10 16:33:28 2013 -0700
@@ -165,14 +165,18 @@
     }
 
     public CodeTreeBuilder startCall(String callSite) {
-        return startCall(null, callSite);
+        return startCall((CodeTree) null, callSite);
     }
 
     public CodeTreeBuilder startCall(String receiver, String callSite) {
+        return startCall(singleString(receiver), callSite);
+    }
+
+    public CodeTreeBuilder startCall(CodeTree receiver, String callSite) {
         if (receiver == null) {
             return startGroup().string(callSite).startParanthesesCommaGroup().endAfter();
         } else {
-            return startGroup().string(receiver).string(".").string(callSite).startParanthesesCommaGroup().endAfter();
+            return startGroup().tree(receiver).string(".").string(callSite).startParanthesesCommaGroup().endAfter();
         }
     }
 
@@ -336,6 +340,10 @@
         return startGroup().string("if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
     }
 
+    public CodeTreeBuilder startFor() {
+        return startGroup().string("for ").startParantheses().endAndWhitespaceAfter().startGroup().endAfter();
+    }
+
     public boolean startIf(boolean elseIf) {
         if (elseIf) {
             startElseIf();
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java	Tue Sep 10 16:33:28 2013 -0700
@@ -61,7 +61,7 @@
     }
 
     @Override
-    public CreateCastData create(TemplateMethod method) {
+    public CreateCastData create(TemplateMethod method, boolean invalid) {
         AnnotationMirror mirror = method.getMarkerAnnotation();
         List<String> childNames = Utils.getAnnotationValueList(String.class, mirror, "value");
         CreateCastData cast = new CreateCastData(method, childNames);
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java	Tue Sep 10 16:33:28 2013 -0700
@@ -73,17 +73,13 @@
 
     @Override
     protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
-        // executable types not yet available
-        if (nodeData.getTypeSystem() == null) {
-            return Collections.emptyList();
-        }
-        List<TypeMirror> types = new ArrayList<>(nodeData.getTypeSystem().getPrimitiveTypeMirrors());
-        types.add(nodeData.getTypeSystem().getVoidType().getPrimitiveType());
+        List<TypeMirror> types = new ArrayList<>(getNode().getTypeSystem().getPrimitiveTypeMirrors());
+        types.add(getNode().getTypeSystem().getVoidType().getPrimitiveType());
         return types;
     }
 
     @Override
-    public ExecutableTypeData create(TemplateMethod method) {
+    public ExecutableTypeData create(TemplateMethod method, boolean invalid) {
         TypeData resolvedType = method.getReturnType().getTypeSystemType();
         return new ExecutableTypeData(method, method.getMethod(), getNode().getTypeSystem(), resolvedType);
     }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java	Tue Sep 10 16:33:28 2013 -0700
@@ -61,7 +61,7 @@
     }
 
     @Override
-    public SpecializationData create(TemplateMethod method) {
+    public SpecializationData create(TemplateMethod method, boolean invalid) {
         SpecializationData data = new SpecializationData(method, true, false, false);
         return data;
     }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java	Tue Sep 10 16:33:28 2013 -0700
@@ -49,6 +49,7 @@
         DEFAULT, SHORT_CIRCUIT
     }
 
+    private final NodeData parent;
     private final Element sourceElement;
     private final AnnotationMirror sourceAnnotationMirror;
 
@@ -64,8 +65,9 @@
 
     private NodeData nodeData;
 
-    public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality,
-                    ExecutionKind executionKind) {
+    public NodeChildData(NodeData parent, Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement,
+                    Cardinality cardinality, ExecutionKind executionKind) {
+        this.parent = parent;
         this.sourceElement = sourceElement;
         this.sourceAnnotationMirror = sourceMirror;
         this.name = name;
@@ -84,6 +86,31 @@
         this.executeWith = executeWith;
     }
 
+    public boolean needsImplicitCast(ProcessorContext context) {
+        if (!parent.needsRewrites(context)) {
+            return false;
+        }
+
+        boolean used = false;
+        SpecializationData generic = parent.getGenericSpecialization();
+        for (ActualParameter param : generic.getParameters()) {
+            if (!param.getSpecification().isSignature()) {
+                continue;
+            }
+            NodeChildData child = parent.findChild(param.getSpecification().getName());
+            if (child == this) {
+                used = true;
+                break;
+            }
+        }
+
+        if (!used) {
+            return false;
+        }
+
+        return getNodeData().getTypeSystem().getImplicitCasts() != null && !getNodeData().getTypeSystem().getImplicitCasts().isEmpty();
+    }
+
     public ExecutableTypeData findExecutableType(ProcessorContext context, TypeData targetType) {
         ExecutableTypeData executableType = nodeData.findExecutableType(targetType, getExecuteWith().size());
         if (executableType == null) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Tue Sep 10 16:33:28 2013 -0700
@@ -62,12 +62,17 @@
         return node.getNodeId() + "Factory";
     }
 
+    private static String nodeCastClassName(NodeData node, TypeData type) {
+        String nodeid = resolveNodeId(node);
+        if (type == null) {
+            return nodeid + "ImplicitCast";
+        } else {
+            return Utils.firstLetterUpperCase(Utils.getSimpleName(type.getPrimitiveType())) + "Cast";
+        }
+    }
+
     private static String nodeSpecializationClassName(SpecializationData specialization) {
-        String nodeid = specialization.getNode().getNodeId();
-        if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
-            nodeid = nodeid.substring(0, nodeid.length() - 4);
-        }
-
+        String nodeid = resolveNodeId(specialization.getNode());
         String name = Utils.firstLetterUpperCase(nodeid);
         name += Utils.firstLetterUpperCase(specialization.getId());
         name += "Node";
@@ -75,10 +80,7 @@
     }
 
     private static String nodePolymorphicClassName(NodeData node, SpecializationData specialization) {
-        String nodeid = node.getNodeId();
-        if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
-            nodeid = nodeid.substring(0, nodeid.length() - 4);
-        }
+        String nodeid = resolveNodeId(node);
 
         String name = Utils.firstLetterUpperCase(nodeid);
         if (specialization == node.getGenericPolymorphicSpecialization()) {
@@ -89,10 +91,22 @@
         return name;
     }
 
+    private static String resolveNodeId(NodeData node) {
+        String nodeid = node.getNodeId();
+        if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
+            nodeid = nodeid.substring(0, nodeid.length() - 4);
+        }
+        return nodeid;
+    }
+
     private static String valueNameEvaluated(ActualParameter targetParameter) {
         return valueName(targetParameter) + "Evaluated";
     }
 
+    private static String typeName(ActualParameter param) {
+        return param.getLocalName() + "Type";
+    }
+
     private static String valueName(ActualParameter param) {
         return param.getLocalName();
     }
@@ -147,7 +161,8 @@
         }
     }
 
-    private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeImplicit) {
+    private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeImplicit,
+                    Map<String, String> customNames) {
         if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
             builder.string("frameValue");
         }
@@ -166,7 +181,9 @@
 
             ActualParameter sourceParameter = source.findParameter(parameter.getLocalName());
 
-            if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) {
+            if (customNames != null && customNames.containsKey(parameter.getLocalName())) {
+                builder.string(customNames.get(parameter.getLocalName()));
+            } else if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) {
                 builder.cast(parameter.getType(), CodeTreeBuilder.singleString("ex.getResult()"));
             } else if (sourceParameter != null) {
                 builder.string(valueName(sourceParameter, parameter));
@@ -298,10 +315,7 @@
     }
 
     private static String baseClassName(NodeData node) {
-        String nodeid = node.getNodeId();
-        if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
-            nodeid = nodeid.substring(0, nodeid.length() - 4);
-        }
+        String nodeid = resolveNodeId(node);
         String name = Utils.firstLetterUpperCase(nodeid);
         name += "BaseNode";
         return name;
@@ -362,7 +376,7 @@
         builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class));
         builder.startCall("createInfo0");
         builder.doubleQuote("Unsupported values");
-        addInternalValueParameterNames(builder, current, current, null, false, true);
+        addInternalValueParameterNames(builder, current, current, null, false, true, null);
         builder.end().end().end();
     }
 
@@ -422,7 +436,11 @@
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     protected void createChildren(NodeData node) {
+        List<CodeTypeElement> casts = new ArrayList<>(getElement().getEnclosedElements());
+        getElement().getEnclosedElements().clear();
+
         Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>();
         if (node.getDeclaredNodes() != null && !node.getDeclaredNodes().isEmpty()) {
             for (NodeData nodeChild : node.getDeclaredNodes()) {
@@ -432,14 +450,35 @@
         }
 
         if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) {
-            add(new NodeFactoryFactory(context, childTypes), node);
+            NodeFactoryFactory factory = new NodeFactoryFactory(context, childTypes);
+            add(factory, node);
+            factory.getElement().getEnclosedElements().addAll(casts);
+        }
+    }
+
+    protected CodeTree createCastType(NodeData node, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) {
+        if (targetType == null) {
+            return value;
+        } else if (sourceType != null && !sourceType.needsCastTo(getContext(), targetType)) {
+            return value;
         }
+
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        String targetMethodName;
+        if (expect) {
+            targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType);
+        } else {
+            targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
+        }
+        startCallTypeSystemMethod(getContext(), builder, node, targetMethodName);
+        builder.tree(value);
+        builder.end().end();
+        return builder.getRoot();
     }
 
     private class NodeFactoryFactory extends ClassElementFactory<NodeData> {
 
         private final Map<NodeData, List<TypeElement>> childTypes;
-
         private CodeTypeElement generatedNode;
 
         public NodeFactoryFactory(ProcessorContext context, Map<NodeData, List<TypeElement>> childElements) {
@@ -621,6 +660,9 @@
 
                 int index = 0;
                 for (VariableElement param : element.getParameters()) {
+                    if (Utils.isObject(param.asType())) {
+                        continue;
+                    }
                     builder.string(" && ");
                     if (!param.asType().getKind().isPrimitive()) {
                         builder.string("(arguments[" + index + "] == null || ");
@@ -639,7 +681,9 @@
                 index = 0;
                 for (VariableElement param : element.getParameters()) {
                     builder.startGroup();
-                    builder.string("(").type(param.asType()).string(") ");
+                    if (!Utils.isObject(param.asType())) {
+                        builder.string("(").type(param.asType()).string(") ");
+                    }
                     builder.string("arguments[").string(String.valueOf(index)).string("]");
                     builder.end();
                     index++;
@@ -848,7 +892,8 @@
                     ExecutableElement getter = (ExecutableElement) child.getAccessElement();
                     CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter);
                     method.getModifiers().remove(Modifier.ABSTRACT);
-                    method.createBuilder().startReturn().string("this.").string(child.getName()).end();
+                    CodeTreeBuilder builder = method.createBuilder();
+                    builder.startReturn().string("this.").string(child.getName()).end();
                     clazz.add(method);
                 }
             }
@@ -1102,29 +1147,58 @@
                 builder.startStatement();
                 String fieldName = var.getSimpleName().toString();
 
-                CodeTree fieldInit = CodeTreeBuilder.singleString(var.getSimpleName().toString());
-                builder.string("this.").string(var.getSimpleName().toString());
-
                 NodeChildData child = node.findChild(fieldName);
-                if (child != null) {
-                    CreateCastData createCast = node.findCast(child.getName());
-                    if (createCast != null) {
-                        fieldInit = createTemplateMethodCall(builder, null, node.getGenericSpecialization(), createCast, null, child.getName());
-                    }
-                }
-
-                if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) {
-                    builder.string(" = adoptChild(").tree(fieldInit).string(")");
-                } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
-                    builder.string(" = adoptChildren(").tree(fieldInit).string(")");
-                } else {
-                    builder.string(" = ").tree(fieldInit);
-                }
+
+                CodeTree init = createStaticCast(builder, child, fieldName);
+                init = createAdoptChild(builder, var.asType(), init);
+
+                builder.string("this.").string(fieldName).string(" = ").tree(init);
                 builder.end();
             }
             return method;
         }
 
+        private CodeTree createStaticCast(CodeTreeBuilder parent, NodeChildData child, String fieldName) {
+            NodeData parentNode = getModel().getNode();
+            if (child != null) {
+                CreateCastData createCast = parentNode.findCast(child.getName());
+                if (createCast != null) {
+                    return createTemplateMethodCall(parent, null, parentNode.getGenericSpecialization(), createCast, null, fieldName);
+                }
+            }
+            return CodeTreeBuilder.singleString(fieldName);
+        }
+
+        private CodeTree createAdoptChild(CodeTreeBuilder parent, TypeMirror type, CodeTree value) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            if (Utils.isAssignable(getContext(), type, getContext().getTruffleTypes().getNode())) {
+                builder.string("adoptChild(").tree(value).string(")");
+            } else if (Utils.isAssignable(getContext(), type, getContext().getTruffleTypes().getNodeArray())) {
+                builder.string("adoptChildren(").tree(value).string(")");
+            } else {
+                builder.tree(value);
+            }
+            return builder.getRoot();
+        }
+
+        private CodeTree createCopyArray(CodeTreeBuilder parent, NodeChildData child, TypeMirror arrayType, CodeBlock<String> accessElement) {
+            CodeTreeBuilder builder = parent.create();
+            NodeData node = getModel().getNode();
+            builder.string("new ").type(arrayType).string(" {");
+            builder.startCommaGroup();
+            for (ActualParameter parameter : getModel().getParameters()) {
+                NodeChildData foundChild = node.findChild(parameter.getSpecification().getName());
+                if (foundChild == child) {
+                    builder.startGroup();
+                    builder.tree(accessElement.create(builder, String.valueOf(parameter.getIndex())));
+                    builder.end();
+                }
+            }
+            builder.end();
+            builder.end().string("}");
+            return builder.getRoot();
+        }
+
         private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
             CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
             CodeTreeBuilder builder = method.createBuilder();
@@ -1136,34 +1210,22 @@
 
             for (VariableElement var : type.getFields()) {
                 builder.startStatement();
-                String varName = var.getSimpleName().toString();
-                builder.string("this.").string(varName);
-                if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) {
-                    builder.string(" = adoptChild(copy.").string(varName).string(")");
-                } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
-                    NodeData node = getModel().getNode();
-                    NodeChildData child = node.findChild(varName);
-                    if (child != null) {
-                        builder.string(" = adoptChildren(");
-                        builder.string("new ").type((child.getNodeType())).string(" {");
-                        builder.startCommaGroup();
-                        for (ActualParameter parameter : getModel().getParameters()) {
-                            NodeChildData foundChild = node.findChild(parameter.getSpecification().getName());
-                            if (foundChild == child) {
-                                builder.startGroup();
-                                builder.string("copy.").string(varName).string("[").string(String.valueOf(parameter.getIndex())).string("]");
-                                builder.end();
-                            }
+                final String varName = var.getSimpleName().toString();
+                final TypeMirror varType = var.asType();
+
+                final String copyAccess = "copy." + varName;
+                CodeTree init = CodeTreeBuilder.singleString(copyAccess);
+                if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
+                    NodeChildData child = getModel().getNode().findChild(varName);
+                    init = createCopyArray(builder, child, varType, new CodeBlock<String>() {
+
+                        public CodeTree create(CodeTreeBuilder parent, String index) {
+                            return CodeTreeBuilder.singleString(copyAccess + "[" + index + "]");
                         }
-
-                        builder.end().string("})");
-                    } else {
-                        builder.string(" = adoptChildren(copy.").string(varName).string(")");
-                    }
-                } else {
-                    builder.string(" = copy.").string(varName);
+                    });
                 }
-                builder.end();
+                init = createAdoptChild(builder, varType, init);
+                builder.startStatement().string("this.").string(varName).string(" = ").tree(init).end();
             }
             if (getModel().getNode().isPolymorphic()) {
                 builder.statement("this.next0 = adoptChild(copy.next0)");
@@ -1179,7 +1241,8 @@
         }
 
         private CodeVariableElement createChildField(NodeChildData child) {
-            CodeVariableElement var = new CodeVariableElement(child.getNodeType(), child.getName());
+            TypeMirror type = child.getNodeType();
+            CodeVariableElement var = new CodeVariableElement(type, child.getName());
             var.getModifiers().add(Modifier.PROTECTED);
 
             DeclaredType annotationType;
@@ -1218,7 +1281,7 @@
             }
 
             builder.startStatement().string("String message = ").startCall("createInfo0").string("reason");
-            addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, true);
+            addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, true, null);
             builder.end().end();
 
             final String currentNodeVar = currentNode;
@@ -1429,7 +1492,7 @@
                     guardsAnd = " && ";
                 }
 
-                CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType());
+                CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType(), minimumState);
                 if (cast != null) {
                     castBuilder.tree(cast);
                 }
@@ -1521,7 +1584,15 @@
                 builder.string(" || ");
             }
 
-            startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(targetType));
+            String castMethodName;
+            List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
+            if (types.size() > 1) {
+                castMethodName = TypeSystemCodeGenerator.isImplicitTypeMethodName(targetType);
+            } else {
+                castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType);
+            }
+
+            startCallTypeSystemMethod(getContext(), builder, node, castMethodName);
             builder.string(valueName(source));
             builder.end().end(); // call
 
@@ -1534,7 +1605,7 @@
             return builder.getRoot();
         }
 
-        private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType) {
+        private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean minimumState) {
             NodeData node = field.getNodeData();
             TypeData sourceType = source.getTypeSystemType();
 
@@ -1549,9 +1620,24 @@
                 condition = CodeTreeBuilder.singleString(valueName(shortCircuit));
             }
 
-            CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), CodeTreeBuilder.singleString(valueName(source)));
-
-            return createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, value);
+            String castMethodName;
+            List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
+            if (types.size() > 1) {
+                castMethodName = TypeSystemCodeGenerator.asImplicitTypeMethodName(targetType);
+            } else {
+                castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
+            }
+
+            CodeTree value = createCallTypeSystemMethod(context, parent, node, castMethodName, CodeTreeBuilder.singleString(valueName(source)));
+
+            CodeTreeBuilder builder = parent.create();
+            builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, value));
+            if (minimumState && types.size() > 1) {
+                CodeTree castType = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.getImplicitClass(targetType), CodeTreeBuilder.singleString(valueName(source)));
+                builder.tree(createLazyAssignment(builder, typeName(source), getContext().getType(Class.class), condition, castType));
+            }
+
+            return builder.getRoot();
         }
 
         private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardData guard) {
@@ -1590,7 +1676,6 @@
                 builder.tree(createRewriteGeneric(builder, source, current, currentNodeVar));
                 builder.end();
             } else {
-                // simple rewrite
                 if (current.getExceptions().isEmpty()) {
                     builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null), null));
                 } else {
@@ -1664,7 +1749,7 @@
             }
             if (current.isGeneric()) {
                 builder.startReturn().tree(replace).string(".").startCall(EXECUTE_GENERIC_NAME);
-                addInternalValueParameterNames(builder, source, current, null, current.getNode().needsFrame(), true);
+                addInternalValueParameterNames(builder, source, current, null, current.getNode().needsFrame(), true, null);
                 builder.end().end();
             } else if (current.getMethod() == null) {
                 if (replaceCall != null) {
@@ -1691,7 +1776,19 @@
             } else {
                 replaceCall.startCall("replace");
             }
-            replaceCall.startGroup().startNew(className).string(source).end().end();
+            replaceCall.startGroup().startNew(className).string(source);
+            for (ActualParameter param : current.getParameters()) {
+                if (!param.getSpecification().isSignature()) {
+                    continue;
+                }
+                NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
+                List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
+                if (types.size() > 1) {
+                    replaceCall.string(typeName(param));
+                }
+            }
+            replaceCall.end().end();
+
             if (message == null) {
                 replaceCall.string("message");
             } else {
@@ -1727,7 +1824,7 @@
 
             builder.startReturn();
             builder.startCall(currentNode + ".next0", executeCachedName(node.getGenericPolymorphicSpecialization()));
-            addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, true);
+            addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, true, null);
             builder.end();
             builder.end();
 
@@ -1771,7 +1868,7 @@
                 executeParameterNames[i] = valueName(executeParameters.get(i));
             }
 
-            builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null, true));
+            builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null));
 
             CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames);
             if (needsTry) {
@@ -1822,134 +1919,193 @@
             return createCastType(node, sourceType, castedType.getType(), hasUnexpected, value);
         }
 
-        protected CodeTree createCastType(NodeData node, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) {
-            if (targetType == null) {
-                return value;
-            } else if (!sourceType.needsCastTo(getContext(), targetType)) {
-                return value;
-            }
-
-            CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-            String targetMethodName;
-            if (expect) {
-                targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType);
-            } else {
-                targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
-            }
-            startCallTypeSystemMethod(getContext(), builder, node, targetMethodName);
-
-            builder.tree(value);
-            builder.end().end();
-            return builder.getRoot();
-        }
-
         protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters,
-                        ActualParameter unexpectedParameter, boolean cast) {
-            NodeData sourceNode = specialization.getNode();
-
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-
+                        ActualParameter unexpectedParameter) {
+            CodeTreeBuilder builder = parent.create();
+            NodeData node = specialization.getNode();
             for (ActualParameter targetParameter : targetParameters) {
-                NodeChildData field = sourceNode.findChild(targetParameter.getSpecification().getName());
+                NodeChildData child = node.findChild(targetParameter.getSpecification().getName());
                 if (!targetParameter.getSpecification().isSignature()) {
                     continue;
                 }
-
                 TypeData targetType = targetParameter.getTypeSystemType();
                 ExecutableTypeData targetExecutable = null;
-                if (field != null) {
-                    targetExecutable = field.findExecutableType(getContext(), targetType);
+                if (child != null) {
+                    targetExecutable = child.findExecutableType(getContext(), targetType);
+                }
+
+                if (targetExecutable == null) {
+                    // TODO what to do? assertion?
+                    continue;
                 }
 
-                ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName());
-
-                String targetVariableName = valueName(targetParameter);
-
-                CodeTree executionExpression = null;
-                if ((sourceParameter != null && cast) || sourceParameter != null) {
-                    TypeData sourceType = sourceParameter.getTypeSystemType();
-                    if (targetExecutable == null || !sourceType.needsCastTo(getContext(), targetType)) {
-                        if (field != null && field.isShortCircuit() && sourceParameter != null) {
-                            builder.tree(createShortCircuitValue(builder, specialization, field, targetParameter.getPreviousParameter(), unexpectedParameter));
-                        }
-                        builder.startStatement();
-                        builder.type(targetParameter.getType()).string(" ");
-                        builder.string(targetVariableName).string(" = ");
-                        builder.tree(CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)));
-                        builder.end();
-                        continue;
+                CodeTree executionExpressions = createExecutionExpresssions(builder, child, sourceExecutable, targetExecutable, targetParameter, unexpectedParameter);
+
+                String targetVarName = valueName(targetParameter);
+                CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, targetVarName, specialization, sourceExecutable, targetExecutable, targetParameter,
+                                isShortCircuit(child));
+                CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, targetVarName, specialization, targetParameter, unexpectedParameter);
+
+                if (shortCircuitTree == executionExpressions) {
+                    if (containsNewLine(executionExpressions)) {
+                        builder.declaration(sourceExecutable.getType().getPrimitiveType(), targetVarName);
+                        builder.tree(shortCircuitTree);
                     } else {
-                        CodeTree valueTree = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter));
-                        executionExpression = createExpectExecutableType(sourceNode, sourceType, targetExecutable, valueTree);
+                        builder.startStatement().type(targetParameter.getType()).string(" ").tree(shortCircuitTree).end();
                     }
-                } else if (sourceParameter == null) {
-                    executionExpression = createExecuteChildExpression(builder, field, targetParameter, unexpectedParameter);
-                }
-
-                if (executionExpression != null) {
-                    CodeTreeVariable executionVar = new CodeTreeVariable();
-                    CodeTree shortCircuitTree = createShortCircuitTree(builder, executionVar, targetVariableName, specialization, targetParameter, unexpectedParameter);
-                    CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpression, targetVariableName, specialization, sourceExecutable, targetExecutable, targetParameter,
-                                    shortCircuitTree != executionVar);
-
-                    executionVar.set(unexpectedTree);
+                } else {
                     builder.tree(shortCircuitTree);
                 }
+
+            }
+            return builder.getRoot();
+        }
+
+        private CodeTree createExecutionExpresssions(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ExecutableTypeData targetExecutable, ActualParameter param,
+                        ActualParameter unexpectedParameter) {
+            CodeTreeBuilder builder = parent.create();
+
+            TypeData type = param.getTypeSystemType();
+            List<TypeData> targetTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(type);
+
+            if (targetTypes.size() > 1) {
+                boolean elseIf = false;
+                int index = 0;
+                for (TypeData typeData : targetTypes) {
+                    if (index < targetTypes.size() - 1) {
+                        elseIf = builder.startIf(elseIf);
+                        builder.string(typeName(param)).string(" == ").typeLiteral(typeData.getPrimitiveType());
+                        builder.end();
+                        builder.startBlock();
+                    } else {
+                        builder.startElseBlock();
+                    }
+
+                    ExecutableTypeData implictExecutableTypeData = child.getNodeData().findExecutableType(typeData, targetExecutable.getEvaluatedCount());
+                    ImplicitCastData cast = child.getNodeData().getTypeSystem().lookupCast(typeData, param.getTypeSystemType());
+                    CodeTree execute = createExecuteExpression(parent, child, sourceExecutable, implictExecutableTypeData, param, unexpectedParameter, cast);
+                    builder.statement(execute);
+                    builder.end();
+                    index++;
+                }
+            } else {
+                builder.tree(createExecuteExpression(parent, child, sourceExecutable, targetExecutable, param, unexpectedParameter, null));
             }
             return builder.getRoot();
         }
 
+        private CodeTree createExecuteExpression(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ExecutableTypeData targetExecutable,
+                        ActualParameter targetParameter, ActualParameter unexpectedParameter, ImplicitCastData cast) {
+            CodeTreeBuilder builder = parent.create();
+            builder.string(valueName(targetParameter));
+            builder.string(" = ");
+            if (cast != null) {
+                startCallTypeSystemMethod(getContext(), builder, child.getNodeData(), cast.getMethodName());
+            }
+
+            if (targetExecutable.getType().needsCastTo(context, targetParameter.getTypeSystemType()) && cast == null) {
+                startCallTypeSystemMethod(getContext(), builder, child.getNodeData(), TypeSystemCodeGenerator.expectTypeMethodName(targetParameter.getTypeSystemType()));
+            }
+
+            NodeData node = getModel().getNode();
+            ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName());
+            if (sourceParameter == null) {
+                builder.tree(createExecuteChildExpression(builder, child, targetParameter, targetExecutable, unexpectedParameter));
+            } else {
+                CodeTree var = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter));
+                builder.tree(createExpectExecutableType(node, sourceParameter.getTypeSystemType(), targetExecutable, var));
+            }
+
+            if (targetExecutable.getType().needsCastTo(context, targetParameter.getTypeSystemType())) {
+                builder.end().end();
+            }
+
+            if (cast != null) {
+                builder.end().end();
+            }
+
+            return builder.getRoot();
+        }
+
+        private boolean containsNewLine(CodeTree tree) {
+            if (tree.getCodeKind() == CodeTreeKind.NEW_LINE) {
+                return true;
+            }
+
+            for (CodeTree codeTree : tree.getEnclosedElements()) {
+                if (containsNewLine(codeTree)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        private boolean hasUnexpected(ExecutableTypeData target, ActualParameter sourceParameter, ActualParameter targetParameter) {
+            List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType());
+            NodeChildData child = getModel().getNode().findChild(targetParameter.getSpecification().getName());
+            boolean hasUnexpected = false;
+            for (TypeData type : types) {
+                if (hasUnexpected) {
+                    continue;
+                }
+                ExecutableTypeData execTarget = target;
+                if (type != execTarget.getType()) {
+                    execTarget = child.findExecutableType(getContext(), type);
+                }
+                hasUnexpected = hasUnexpected || hasUnexpectedType(execTarget, sourceParameter, type);
+            }
+            return hasUnexpected;
+        }
+
+        private boolean hasUnexpectedType(ExecutableTypeData target, ActualParameter sourceParameter, TypeData type) {
+            boolean targetCast = target.getType().needsCastTo(context, type);
+            if (targetCast && getModel().getNode().getTypeSystem().lookupCast(target.getType(), type) == null) {
+                return true;
+            }
+            if (sourceParameter == null) {
+                return target.hasUnexpectedValue(getContext());
+            } else {
+                if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), type)) {
+                    return target.hasUnexpectedValue(getContext());
+                }
+                return false;
+            }
+        }
+
         private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ExecutableTypeData currentExecutable,
                         ExecutableTypeData targetExecutable, ActualParameter param, boolean shortCircuit) {
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            boolean unexpected = targetExecutable.hasUnexpectedValue(getContext());
-            boolean cast = false;
-            if (targetExecutable.getType().needsCastTo(getContext(), param.getTypeSystemType())) {
-                unexpected = true;
-                cast = true;
+            ActualParameter sourceParameter = currentExecutable.findParameter(param.getLocalName());
+            boolean unexpected = hasUnexpected(targetExecutable, sourceParameter, param);
+            if (!unexpected) {
+                return body;
             }
 
-            builder.startStatement();
-
             if (!shortCircuit) {
-                builder.type(param.getType()).string(" ").string(targetVariableName);
+                builder.declaration(param.getType(), targetVariableName);
             }
-
-            if (unexpected) {
-                if (!shortCircuit) {
-                    builder.end();
-                }
-                builder.startTryBlock();
-                builder.startStatement();
-                builder.string(targetVariableName);
-            } else if (shortCircuit) {
-                builder.startStatement();
-                builder.string(targetVariableName);
-            }
-            builder.string(" = ");
-            if (cast) {
-                builder.tree(createCastType(specialization.getNode(), targetExecutable.getType(), param.getTypeSystemType(), true, body));
-            } else {
+            builder.startTryBlock();
+
+            if (containsNewLine(body)) {
                 builder.tree(body);
+            } else {
+                builder.statement(body);
             }
-            builder.end();
-
-            if (unexpected) {
-                builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
-                SpecializationData generic = specialization.getNode().getGenericSpecialization();
-                ActualParameter genericParameter = generic.findParameter(param.getLocalName());
-
-                List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter);
-                builder.tree(createDeoptimize(builder));
-                builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false));
-                if (specialization.isPolymorphic()) {
-                    builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param));
-                } else {
-                    builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization, param,
-                                    "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType())));
-                }
-                builder.end(); // catch block
+
+            builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
+            SpecializationData generic = specialization.getNode().getGenericSpecialization();
+            ActualParameter genericParameter = generic.findParameter(param.getLocalName());
+
+            List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter);
+            builder.tree(createDeoptimize(builder));
+            builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter));
+            if (specialization.isPolymorphic()) {
+                builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param));
+            } else {
+                builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization, param,
+                                "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType())));
             }
+            builder.end(); // catch block
 
             return builder.getRoot();
         }
@@ -1964,7 +2120,7 @@
 
             CodeTreeBuilder execute = new CodeTreeBuilder(builder);
             execute.startCall("next0", executeCachedName(generic));
-            addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true);
+            addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true, null);
             execute.end();
 
             TypeData sourceType = generic.getReturnType().getTypeSystemType();
@@ -1975,37 +2131,26 @@
             return builder.getRoot();
         }
 
-        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetField, ActualParameter sourceParameter, ActualParameter unexpectedParameter) {
-            TypeData type = sourceParameter.getTypeSystemType();
-            ExecutableTypeData execType = targetField.findExecutableType(getContext(), type);
-
+        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetChild, ActualParameter targetParameter, ExecutableTypeData targetExecutable,
+                        ActualParameter unexpectedParameter) {
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            if (targetField != null) {
-                Element accessElement = targetField.getAccessElement();
-                if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) {
-                    builder.string("this.").string(targetField.getName());
-                } else if (accessElement.getKind() == ElementKind.FIELD) {
-                    builder.string("this.").string(accessElement.getSimpleName().toString());
-                } else {
-                    throw new AssertionError();
-                }
-                if (sourceParameter.getSpecification().isIndexed()) {
-                    builder.string("[" + sourceParameter.getIndex() + "]");
-                }
+            if (targetChild != null) {
+                builder.tree(createAccessChild(builder, targetChild, targetParameter));
                 builder.string(".");
             }
 
-            builder.startCall(execType.getMethodName());
-
+            builder.startCall(targetExecutable.getMethodName());
+
+            // TODO this should be merged with #createTemplateMethodCall
             int index = 0;
-            for (ActualParameter parameter : execType.getParameters()) {
+            for (ActualParameter parameter : targetExecutable.getParameters()) {
 
                 if (!parameter.getSpecification().isSignature()) {
                     builder.string(parameter.getLocalName());
                 } else {
 
-                    if (index < targetField.getExecuteWith().size()) {
-                        NodeChildData child = targetField.getExecuteWith().get(index);
+                    if (index < targetChild.getExecuteWith().size()) {
+                        NodeChildData child = targetChild.getExecuteWith().get(index);
 
                         ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName());
                         List<ActualParameter> specializationParams = getModel().findParameters(spec);
@@ -2044,32 +2189,50 @@
             return builder.getRoot();
         }
 
+        private CodeTree createAccessChild(CodeTreeBuilder parent, NodeChildData targetChild, ActualParameter targetParameter) throws AssertionError {
+            CodeTreeBuilder builder = parent.create();
+            Element accessElement = targetChild.getAccessElement();
+            if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) {
+                builder.string("this.").string(targetChild.getName());
+            } else if (accessElement.getKind() == ElementKind.FIELD) {
+                builder.string("this.").string(accessElement.getSimpleName().toString());
+            } else {
+                throw new AssertionError();
+            }
+            if (targetParameter.getSpecification().isIndexed()) {
+                builder.string("[" + targetParameter.getIndex() + "]");
+            }
+            return builder.getRoot();
+        }
+
         private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ActualParameter parameter,
                         ActualParameter exceptionParam) {
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-
             NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName());
-            if (forField == null) {
+            if (!isShortCircuit(forField)) {
                 return body;
             }
 
-            if (forField.getExecutionKind() != ExecutionKind.SHORT_CIRCUIT) {
-                return body;
-            }
-
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter);
-
             builder.tree(createShortCircuitValue(builder, specialization, forField, shortCircuitParam, exceptionParam));
-
             builder.declaration(parameter.getType(), targetVariableName, CodeTreeBuilder.createBuilder().defaultValue(parameter.getType()));
             builder.startIf().string(shortCircuitParam.getLocalName()).end();
             builder.startBlock();
-            builder.tree(body);
+
+            if (containsNewLine(body)) {
+                builder.tree(body);
+            } else {
+                builder.statement(body);
+            }
             builder.end();
 
             return builder.getRoot();
         }
 
+        private boolean isShortCircuit(NodeChildData forField) {
+            return forField != null && forField.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT;
+        }
+
         private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeChildData forField, ActualParameter shortCircuitParam, ActualParameter exceptionParam) {
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             int shortCircuitIndex = 0;
@@ -2104,7 +2267,7 @@
             CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
             specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);
             specializeCall.string(String.valueOf(node.getSpecializations().indexOf(current)));
-            addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true);
+            addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true, null);
             specializeCall.doubleQuote(reason);
             specializeCall.end().end();
 
@@ -2194,6 +2357,233 @@
         }
     }
 
+    private class BaseCastNodeFactory extends ClassElementFactory<NodeData> {
+
+        protected final Set<TypeData> usedTargetTypes;
+
+        public BaseCastNodeFactory(ProcessorContext context, Set<TypeData> usedTargetTypes) {
+            super(context);
+            this.usedTargetTypes = usedTargetTypes;
+        }
+
+        @Override
+        protected CodeTypeElement create(NodeData m) {
+            CodeTypeElement type = createClass(m, modifiers(STATIC), nodeCastClassName(m, null), context.getTruffleTypes().getNode(), false);
+
+            CodeVariableElement delegate = new CodeVariableElement(m.getNodeType(), "delegate");
+            delegate.getModifiers().add(PROTECTED);
+            delegate.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation()));
+
+            type.add(delegate);
+            type.add(createConstructorUsingFields(modifiers(), type));
+            return type;
+        }
+
+        @Override
+        protected void createChildren(NodeData m) {
+            CodeTypeElement type = getElement();
+            type.add(createExecute(EXECUTE_SPECIALIZE_NAME, true));
+            type.add(createExecute(EXECUTE_GENERIC_NAME, false));
+
+            for (ExecutableTypeData targetExecutable : m.getExecutableTypes()) {
+                if (!usedTargetTypes.contains(targetExecutable.getType()) && targetExecutable.hasUnexpectedValue(getContext())) {
+                    continue;
+                }
+                CodeExecutableElement execute = createCastExecute(targetExecutable, targetExecutable, false);
+                CodeExecutableElement expect = createCastExecute(targetExecutable, targetExecutable, true);
+                if (execute != null) {
+                    getElement().add(execute);
+                }
+                if (expect != null) {
+                    getElement().add(expect);
+                }
+            }
+            Set<TypeData> sourceTypes = new TreeSet<>();
+            List<ImplicitCastData> casts = getModel().getTypeSystem().getImplicitCasts();
+            for (ImplicitCastData cast : casts) {
+                sourceTypes.add(cast.getSourceType());
+            }
+
+            CodeTypeElement baseType = getElement();
+            for (TypeData sourceType : sourceTypes) {
+                add(new SpecializedCastNodeFactory(context, baseType, sourceType, usedTargetTypes), getModel());
+            }
+        }
+
+        private CodeExecutableElement createExecute(String name, boolean specialize) {
+            NodeData node = getModel();
+            TypeMirror objectType = node.getTypeSystem().getGenericType();
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), objectType, name, new CodeVariableElement(objectType, "value"));
+            if (specialize) {
+                method.getModifiers().add(FINAL);
+            }
+            CodeTreeBuilder builder = method.createBuilder();
+
+            List<ImplicitCastData> casts = node.getTypeSystem().getImplicitCasts();
+            boolean elseIf = false;
+            for (ImplicitCastData cast : casts) {
+                elseIf = builder.startIf(elseIf);
+                startCallTypeSystemMethod(context, builder, getModel(), TypeSystemCodeGenerator.isTypeMethodName(cast.getSourceType()));
+                builder.string("value");
+                builder.end().end();
+                builder.end();
+                builder.startBlock();
+
+                if (specialize) {
+                    builder.startStatement().startCall("replace").startNew(nodeCastClassName(getModel(), cast.getSourceType())).string("delegate").end().doubleQuote("Added cast").end().end();
+                }
+                builder.startReturn();
+
+                startCallTypeSystemMethod(context, builder, getModel(), cast.getMethodName());
+                startCallTypeSystemMethod(context, builder, getModel(), TypeSystemCodeGenerator.asTypeMethodName(cast.getSourceType()));
+                builder.string("value");
+                builder.end().end();
+                builder.end().end();
+
+                builder.end();
+                builder.end();
+            }
+
+            builder.startReturn().string("value").end();
+
+            return method;
+        }
+
+        protected CodeExecutableElement createCastExecute(ExecutableTypeData sourceExecutable, ExecutableTypeData targetExecutable, boolean expect) {
+            ImplicitCastData cast = null;
+            if (!sourceExecutable.getType().equals(targetExecutable.getType())) {
+                cast = getModel().getTypeSystem().lookupCast(sourceExecutable.getType(), targetExecutable.getType());
+                if (cast == null) {
+                    return null;
+                }
+            }
+
+            if (expect) {
+                if (targetExecutable.getEvaluatedCount() > 0) {
+                    return null;
+                } else if (Utils.isObject(targetExecutable.getType().getPrimitiveType())) {
+                    return null;
+                }
+            }
+
+            boolean hasTargetUnexpected = targetExecutable.hasUnexpectedValue(getContext());
+            boolean hasSourceUnexpected = sourceExecutable.hasUnexpectedValue(getContext());
+
+            CodeExecutableElement method = copyTemplateMethod(targetExecutable);
+            method.getModifiers().add(PUBLIC);
+
+            CodeTreeBuilder builder = method.createBuilder();
+
+            if (hasSourceUnexpected && cast != null) {
+                builder.startTryBlock();
+            }
+
+            if (expect) {
+                method.getParameters().clear();
+                String expectMethodName;
+                if (hasTargetUnexpected) {
+                    expectMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetExecutable.getType());
+                } else {
+                    expectMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetExecutable.getType());
+                }
+                method.setSimpleName(CodeNames.of(expectMethodName));
+                method.addParameter(new CodeVariableElement(getModel().getTypeSystem().getGenericType(), "value"));
+            }
+
+            builder.startReturn();
+            CodeTree executeCall;
+            if (expect) {
+                executeCall = createCastType(getModel(), getModel().getTypeSystem().getGenericTypeData(), sourceExecutable.getType(), hasSourceUnexpected, CodeTreeBuilder.singleString("value"));
+            } else {
+                executeCall = createTemplateMethodCall(builder, CodeTreeBuilder.singleString("delegate."), targetExecutable, sourceExecutable, null);
+            }
+            if (cast != null) {
+                startCallTypeSystemMethod(context, builder, getModel(), cast.getMethodName());
+                builder.tree(executeCall);
+                builder.end().end();
+            } else {
+                builder.tree(executeCall);
+            }
+            builder.end();
+
+            if (hasSourceUnexpected && cast != null) {
+                builder.end();
+                builder.startCatchBlock(getContext().getTruffleTypes().getUnexpectedValueException(), "ex");
+                builder.startStatement().startCall("replace").startNew(nodeCastClassName(getModel(), null)).string("delegate").end().doubleQuote("Removed cast").end().end();
+
+                if (hasTargetUnexpected) {
+                    builder.startThrow().string("ex").end();
+                } else {
+                    builder.startThrow().startNew(getContext().getType(AssertionError.class)).end().end();
+                }
+                builder.end();
+            }
+
+            return method;
+        }
+
+        private CodeExecutableElement copyTemplateMethod(TemplateMethod targetExecutable) {
+            CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), targetExecutable.getMethod());
+            method.getModifiers().remove(ABSTRACT);
+            method.getAnnotationMirrors().clear();
+            Modifier visibility = Utils.getVisibility(method.getModifiers());
+            if (visibility != null) {
+                method.getModifiers().remove(visibility);
+            }
+            int index = 0;
+            for (ActualParameter parameter : targetExecutable.getParameters()) {
+                ((CodeVariableElement) method.getParameters().get(index)).setName(parameter.getLocalName());
+                index++;
+            }
+            return method;
+        }
+
+    }
+
+    private class SpecializedCastNodeFactory extends BaseCastNodeFactory {
+
+        private final CodeTypeElement baseType;
+        private final TypeData sourceType;
+
+        public SpecializedCastNodeFactory(ProcessorContext context, CodeTypeElement baseType, TypeData type, Set<TypeData> usedTargetTypes) {
+            super(context, usedTargetTypes);
+            this.baseType = baseType;
+            this.sourceType = type;
+        }
+
+        @Override
+        protected CodeTypeElement create(NodeData m) {
+            CodeTypeElement type = createClass(m, modifiers(PRIVATE, STATIC, FINAL), nodeCastClassName(m, sourceType), baseType.asType(), false);
+            type.add(createConstructorUsingFields(modifiers(), type));
+            return type;
+        }
+
+        @Override
+        protected void createChildren(NodeData node) {
+            for (TypeData targetType : usedTargetTypes) {
+                for (ExecutableTypeData targetExecutable : node.getExecutableTypes()) {
+                    if (targetExecutable.getType().equals(targetType)) {
+                        ExecutableTypeData sourceExecutable = node.findExecutableType(sourceType, targetExecutable.getEvaluatedCount());
+                        if (sourceExecutable == null) {
+                            // TODO what if there is no evaluated version?
+                            continue;
+                        }
+                        CodeExecutableElement execute = createCastExecute(sourceExecutable, targetExecutable, false);
+                        CodeExecutableElement expect = createCastExecute(sourceExecutable, targetExecutable, true);
+                        if (execute != null) {
+                            getElement().add(execute);
+                        }
+                        if (expect != null) {
+                            getElement().add(expect);
+                        }
+                    }
+                }
+
+            }
+        }
+
+    }
+
     private class SpecializedNodeFactory extends NodeBaseFactory {
 
         protected final CodeTypeElement nodeGen;
@@ -2272,15 +2662,31 @@
                 }
 
                 CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor);
+                CodeTree body = superConstructor.getBodyTree();
+                CodeTreeBuilder builder = superConstructor.createBuilder();
+                builder.tree(body);
 
                 if (superConstructor != null) {
                     if (getModel().isGeneric() && node.isPolymorphic()) {
-                        CodeTree body = superConstructor.getBodyTree();
-                        CodeTreeBuilder builder = superConstructor.createBuilder();
-                        builder.tree(body);
                         builder.statement("this.next0 = null");
                     }
 
+                    for (ActualParameter param : getModel().getParameters()) {
+                        if (!param.getSpecification().isSignature()) {
+                            continue;
+                        }
+                        NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
+                        List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
+                        if (types.size() > 1) {
+                            clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), typeName(param)));
+                            superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), typeName(param)));
+
+                            builder.startStatement();
+                            builder.string("this.").string(typeName(param)).string(" = ").string(typeName(param));
+                            builder.end();
+                        }
+                    }
+
                     clazz.add(superConstructor);
                 }
             }
@@ -2328,7 +2734,7 @@
                 } else {
                     CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder);
                     elseBuilder.startReturn().startCall("this.next0", executeCachedName(polymorphic));
-                    addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true);
+                    addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true, null);
                     elseBuilder.end().end();
 
                     boolean forceElse = specialization.getExceptions().size() > 0;
@@ -2370,7 +2776,7 @@
             CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder);
             specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);
             specializeCall.string("0");
-            addInternalValueParameterNames(specializeCall, specialization, node.getGenericSpecialization(), null, true, true);
+            addInternalValueParameterNames(specializeCall, specialization, node.getGenericSpecialization(), null, true, true, null);
             specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end();
             specializeCall.end().end();
 
@@ -2392,15 +2798,13 @@
         }
 
         private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) {
-            TypeData primaryType = specialization.getReturnType().getTypeSystemType();
-
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
 
             List<ExecutableTypeData> primaryExecutes = findFunctionalExecutableType(specialization, execType.getEvaluatedCount());
 
             if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) {
                 builder.tree(createFunctionalExecute(builder, specialization, execType));
-            } else if (needsCastingExecuteMethod(execType, primaryType)) {
+            } else if (needsCastingExecuteMethod(execType)) {
                 assert !primaryExecutes.isEmpty();
                 builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0)));
             } else {
@@ -2431,13 +2835,10 @@
             return method;
         }
 
-        private boolean needsCastingExecuteMethod(ExecutableTypeData execType, TypeData primaryType) {
+        private boolean needsCastingExecuteMethod(ExecutableTypeData execType) {
             if (execType.isAbstract()) {
                 return true;
             }
-            if (Utils.isPrimitiveOrVoid(primaryType.getPrimitiveType()) && Utils.isPrimitiveOrVoid(execType.getType().getPrimitiveType())) {
-                return true;
-            }
             if (execType.getType().isGeneric()) {
                 return true;
             }
@@ -2482,7 +2883,7 @@
                 builder.tree(createDeoptimize(builder));
             }
 
-            builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null, false));
+            builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null));
 
             CodeTree returnSpecialized = null;
 
@@ -2519,26 +2920,25 @@
             CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent);
             if (specialization.isPolymorphic()) {
                 returnBuilder.startCall("next0", executeCachedName(specialization));
-                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
+                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true, null);
                 returnBuilder.end();
             } else if (specialization.isUninitialized()) {
                 returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME);
                 returnBuilder.string("0");
-                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
+                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true, null);
                 returnBuilder.doubleQuote("Uninitialized monomorphic");
                 returnBuilder.end();
             } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
                 emitEncounteredSynthetic(builder, specialization);
             } else if (specialization.isGeneric()) {
                 returnBuilder.startCall("super", EXECUTE_GENERIC_NAME);
-                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, node.needsFrame(), true);
+                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, node.needsFrame(), true, null);
                 returnBuilder.end();
             } else {
                 returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null));
             }
 
             if (!returnBuilder.isEmpty()) {
-
                 ExecutableTypeData sourceExecutableType = node.findExecutableType(specialization.getReturnType().getTypeSystemType(), 0);
                 boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext());
                 boolean targetSupportsUnexpected = executable.hasUnexpectedValue(getContext());
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java	Tue Sep 10 16:33:28 2013 -0700
@@ -32,7 +32,7 @@
 import com.oracle.truffle.dsl.processor.template.*;
 import com.oracle.truffle.dsl.processor.typesystem.*;
 
-public class NodeData extends Template {
+public class NodeData extends Template implements Comparable<NodeData> {
 
     private final String nodeId;
     private NodeData declaringNode;
@@ -90,6 +90,15 @@
         return false;
     }
 
+    public boolean needsImplicitCast(ProcessorContext context) {
+        for (NodeChildData child : getChildren()) {
+            if (child.needsImplicitCast(context)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     public int getPolymorphicDepth() {
         return polymorphicDepth;
     }
@@ -574,4 +583,7 @@
         return null;
     }
 
+    public int compareTo(NodeData o) {
+        return getNodeId().compareTo(o.getNodeId());
+    }
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java	Tue Sep 10 16:33:28 2013 -0700
@@ -85,10 +85,14 @@
         return methodSpec;
     }
 
-    private void addDefaultChildren(boolean shortCircuitsEnabled, String shortCircuitName, MethodSpec methodSpec) {
+    public void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec methodSpec) {
         // children are null when parsing executable types
         if (getNode().getChildren() != null) {
             for (NodeChildData child : getNode().getChildren()) {
+                String valueName = child.getName();
+                if (breakName != null && valueName.equals(breakName)) {
+                    break;
+                }
                 if (child.getExecutionKind() == ExecutionKind.DEFAULT) {
                     ParameterSpec spec = createValueParameterSpec(child.getName(), child.getNodeData(), child.getExecuteWith().size());
                     if (child.getCardinality().isMany()) {
@@ -97,10 +101,6 @@
                     }
                     methodSpec.addRequired(spec);
                 } else if (child.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) {
-                    String valueName = child.getName();
-                    if (shortCircuitName != null && valueName.equals(shortCircuitName)) {
-                        break;
-                    }
 
                     if (shortCircuitsEnabled) {
                         methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class)));
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Tue Sep 10 16:33:28 2013 -0700
@@ -199,6 +199,10 @@
         }
 
         for (NodeData splittedNode : nodes) {
+            if (templateType.getModifiers().contains(Modifier.PRIVATE) && splittedNode.getSpecializations().size() > 0) {
+                splittedNode.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName());
+            }
+
             finalizeSpecializations(elements, splittedNode);
             verifyNode(splittedNode, elements);
             createPolymorphicSpecializations(splittedNode);
@@ -328,10 +332,12 @@
         nodeData.setNodeContainer(nodeContainer != null);
         nodeData.setTypeSystem(typeSystem);
         nodeData.setFields(parseFields(typeHierarchy, elements));
+        nodeData.setChildren(parseChildren(nodeData, elements, typeHierarchy));
+        nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
+
+        // resolveChildren invokes cyclic parsing.
         parsedNodes.put(Utils.getQualifiedName(templateType), nodeData);
-        // parseChildren invokes cyclic parsing.
-        nodeData.setChildren(parseChildren(elements, typeHierarchy));
-        nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
+        resolveChildren(nodeData);
 
         return nodeData;
     }
@@ -380,7 +386,28 @@
         return fields;
     }
 
-    private List<NodeChildData> parseChildren(List<? extends Element> elements, final List<TypeElement> typeHierarchy) {
+    private void resolveChildren(NodeData node) {
+        for (NodeChildData nodeChild : node.getChildren()) {
+            NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(nodeChild.getNodeType()));
+            nodeChild.setNode(fieldNodeData);
+            if (fieldNodeData == null) {
+                nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(nodeChild.getNodeType()));
+            } else if (!Utils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) {
+                nodeChild.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(),
+                                NodeChild.class.getSimpleName(), Utils.getSimpleName(node.getTypeSystem().getTemplateType()), Utils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType()));
+            }
+            if (fieldNodeData != null) {
+                List<ExecutableTypeData> types = nodeChild.findGenericExecutableTypes(context);
+                if (types.isEmpty()) {
+                    AnnotationValue executeWithValue = Utils.getAnnotationValue(nodeChild.getMessageAnnotation(), "executeWith");
+                    nodeChild.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", nodeChild.getExecuteWith().size(),
+                                    Utils.getSimpleName(nodeChild.getNodeType()));
+                }
+            }
+        }
+    }
+
+    private List<NodeChildData> parseChildren(NodeData parent, List<? extends Element> elements, final List<TypeElement> typeHierarchy) {
         Set<String> shortCircuits = new HashSet<>();
         for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
             AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
@@ -445,7 +472,7 @@
                     kind = ExecutionKind.SHORT_CIRCUIT;
                 }
 
-                NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality, kind);
+                NodeChildData nodeChild = new NodeChildData(parent, type, childMirror, name, childType, originalChildType, getter, cardinality, kind);
 
                 parsedChildren.add(nodeChild);
 
@@ -454,12 +481,6 @@
                     continue;
                 }
 
-                NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(childType));
-                nodeChild.setNode(fieldNodeData);
-                if (fieldNodeData == null) {
-                    nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(childType));
-                }
-
                 index++;
             }
         }
@@ -512,12 +533,6 @@
             if (child.getNodeData() == null) {
                 continue;
             }
-
-            List<ExecutableTypeData> types = child.findGenericExecutableTypes(context);
-            if (types.isEmpty()) {
-                child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", executeWith.size(), Utils.getSimpleName(child.getNodeType()));
-                continue;
-            }
         }
 
         return filteredChildren;
@@ -1006,9 +1021,6 @@
         for (TemplateMethod method : nodeData.getAllTemplateMethods()) {
             unusedElements.remove(method.getMethod());
         }
-        if (nodeData.getExtensionElements() != null) {
-            unusedElements.removeAll(nodeData.getExtensionElements());
-        }
 
         for (NodeFieldData field : nodeData.getFields()) {
             if (field.getGetter() != null) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java	Tue Sep 10 16:33:28 2013 -0700
@@ -58,7 +58,7 @@
     }
 
     @Override
-    public ShortCircuitData create(TemplateMethod method) {
+    public ShortCircuitData create(TemplateMethod method, boolean invalid) {
         String shortCircuitValue = Utils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value");
 
         if (!shortCircuitValues.contains(shortCircuitValue)) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java	Tue Sep 10 16:33:28 2013 -0700
@@ -41,12 +41,14 @@
     private final List<TypeGuard> typeGuards;
     private final List<GuardData> guards;
 
+    private final NodeData node;
     private final SpecializationData specialization;
     private final List<SpecializationGroup> children = new ArrayList<>();
 
     private SpecializationGroup parent;
 
     private SpecializationGroup(SpecializationData data) {
+        this.node = data.getNode();
         this.assumptions = new ArrayList<>();
         this.typeGuards = new ArrayList<>();
         this.guards = new ArrayList<>();
@@ -61,9 +63,11 @@
     }
 
     public SpecializationGroup(List<SpecializationGroup> children, List<String> assumptionMatches, List<TypeGuard> typeGuardsMatches, List<GuardData> guardMatches) {
+        assert !children.isEmpty() : "children must not be empty";
         this.assumptions = assumptionMatches;
         this.typeGuards = typeGuardsMatches;
         this.guards = guardMatches;
+        this.node = children.get(0).node;
         this.specialization = null;
         updateChildren(children);
     }
@@ -106,18 +110,23 @@
     }
 
     private GuardData findNegatedGuardInPrevious(GuardData guard) {
-        SpecializationGroup previous = this;
-        while ((previous = previous.getPreviousGroup()) != null) {
-            List<GuardData> elseConnectedGuards = previous.getElseConnectableGuards();
+        SpecializationGroup previous = this.getPreviousGroup();
+        if (previous == null) {
+            return null;
+        }
+        List<GuardData> elseConnectedGuards = previous.getElseConnectableGuards();
 
-            if (previous == null || previous.getGuards().size() != elseConnectedGuards.size() + 1) {
-                return null;
-            }
-            GuardData previousGuard = previous.getGuards().get(elseConnectedGuards.size());
-            if (guard.getMethod().equals(previousGuard.getMethod())) {
-                assert guard.isNegated() != previousGuard.isNegated();
-                return guard;
-            }
+        if (previous == null || previous.getGuards().size() != elseConnectedGuards.size() + 1) {
+            return null;
+        }
+
+        if (elseConnectedGuards.contains(guard)) {
+            return guard;
+        }
+
+        GuardData previousGuard = previous.getGuards().get(elseConnectedGuards.size());
+        if (guard.getMethod().equals(previousGuard.getMethod()) && guard.isNegated() != previousGuard.isNegated()) {
+            return guard;
         }
         return null;
     }
@@ -205,16 +214,29 @@
         for (Iterator<GuardData> iterator = guardMatches.iterator(); iterator.hasNext();) {
             GuardData guardMatch = iterator.next();
 
-            List<TypeMirror> guardTypes = TemplateMethod.getSignatureTypes(guardMatch.getParameters());
-            for (int i = 0; i < guardTypes.size(); i++) {
-                TypeMirror guardType = guardTypes.get(i);
-                int signatureIndex = i + 1;
+            int signatureIndex = 0;
+            for (ActualParameter parameter : guardMatch.getParameters()) {
+                signatureIndex++;
+                if (!parameter.getSpecification().isSignature()) {
+                    continue;
+                }
+
+                TypeMirror guardType = parameter.getType();
 
                 // object guards can be safely moved up
                 if (Utils.isObject(guardType)) {
                     continue;
                 }
 
+                // generic guards can be safely moved up
+                SpecializationData generic = first.node.getGenericSpecialization();
+                if (generic != null) {
+                    ActualParameter genericParameter = generic.findParameter(parameter.getLocalName());
+                    if (genericParameter != null && Utils.typeEquals(genericParameter.getType(), guardType)) {
+                        continue;
+                    }
+                }
+
                 // signature index required for moving up guards
                 if (containsIndex(typeGuardsMatches, signatureIndex) || (first.getParent() != null && first.getParent().containsTypeGuardIndex(signatureIndex))) {
                     continue;
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.java	Tue Sep 10 16:33:28 2013 -0700
@@ -47,7 +47,7 @@
     }
 
     @Override
-    public SpecializationListenerData create(TemplateMethod method) {
+    public SpecializationListenerData create(TemplateMethod method, boolean invalid) {
         return new SpecializationListenerData(method);
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java	Tue Sep 10 16:33:28 2013 -0700
@@ -44,7 +44,7 @@
     }
 
     @Override
-    public SpecializationData create(TemplateMethod method) {
+    public SpecializationData create(TemplateMethod method, boolean invalid) {
         return parseSpecialization(method);
     }
 
@@ -57,7 +57,6 @@
         int order = Utils.getAnnotationValue(Integer.class, method.getMarkerAnnotation(), "order");
         if (order < 0 && order != Specialization.DEFAULT_ORDER) {
             method.addError("Invalid order attribute %d. The value must be >= 0 or the default value.");
-            return null;
         }
 
         AnnotationValue rewriteValue = Utils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn");
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java	Tue Sep 10 16:33:28 2013 -0700
@@ -51,13 +51,21 @@
 
     public abstract Element getMessageElement();
 
-    public final void emitMessages(TypeElement baseElement, Log log) {
-        emitMessagesImpl(baseElement, log, new HashSet<MessageContainer>());
+    public final void emitMessages(ProcessorContext context, TypeElement baseElement, Log log) {
+        emitMessagesImpl(context, baseElement, log, new HashSet<MessageContainer>(), null);
     }
 
-    private void emitMessagesImpl(TypeElement baseElement, Log log, Set<MessageContainer> visitedSinks) {
+    private void emitMessagesImpl(ProcessorContext context, TypeElement baseElement, Log log, Set<MessageContainer> visitedSinks, List<Message> verifiedMessages) {
+        List<Message> childMessages;
+        if (verifiedMessages == null) {
+            childMessages = collectMessagesWithElementChildren(new HashSet<MessageContainer>(), getMessageElement());
+        } else {
+            childMessages = verifiedMessages;
+        }
+        verifyExpectedMessages(context, log, childMessages);
+
         for (Message message : getMessages()) {
-            emitDefault(baseElement, log, message);
+            emitDefault(context, baseElement, log, message);
         }
 
         for (MessageContainer sink : findChildContainers()) {
@@ -66,18 +74,95 @@
             }
 
             visitedSinks.add(sink);
-            sink.emitMessagesImpl(baseElement, log, visitedSinks);
+            if (sink.getMessageElement() == this.getMessageElement()) {
+                sink.emitMessagesImpl(context, baseElement, log, visitedSinks, childMessages);
+            } else {
+                sink.emitMessagesImpl(context, baseElement, log, visitedSinks, null);
+            }
+        }
+    }
+
+    private List<Message> collectMessagesWithElementChildren(Set<MessageContainer> visitedSinks, Element e) {
+        if (visitedSinks.contains(this)) {
+            return Collections.emptyList();
+        }
+        visitedSinks.add(this);
+
+        List<Message> foundMessages = new ArrayList<>();
+        if (Utils.typeEquals(getMessageElement().asType(), e.asType())) {
+            foundMessages.addAll(getMessages());
+        }
+        for (MessageContainer sink : findChildContainers()) {
+            foundMessages.addAll(sink.collectMessagesWithElementChildren(visitedSinks, e));
+        }
+        return foundMessages;
+    }
+
+    private void verifyExpectedMessages(ProcessorContext context, Log log, List<Message> msgs) {
+        TypeElement expectError = context.getTruffleTypes().getExpectError();
+        if (expectError != null) {
+            Element element = getMessageElement();
+            AnnotationMirror mirror = Utils.findAnnotationMirror(element.getAnnotationMirrors(), expectError);
+            if (mirror != null) {
+                List<String> values = Utils.getAnnotationValueList(String.class, mirror, "value");
+                if (values == null) {
+                    values = Collections.emptyList();
+                }
+                if (values.size() != msgs.size()) {
+                    log.message(Kind.ERROR, element, mirror, Utils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size()));
+                }
+            }
         }
     }
 
-    private void emitDefault(TypeElement baseType, Log log, Message message) {
+    private void emitDefault(ProcessorContext context, TypeElement baseType, Log log, Message message) {
+        Kind kind = message.getKind();
+
+        Element messageElement = getMessageElement();
+        AnnotationMirror messageAnnotation = getMessageAnnotation();
+        AnnotationValue messageValue = getMessageAnnotationValue();
+        if (message.getAnnotationValue() != null) {
+            messageValue = message.getAnnotationValue();
+        }
+
+        String text = message.getText();
+
         TypeElement rootEnclosing = Utils.findRootEnclosingType(getMessageElement());
-        if (rootEnclosing != null && Utils.typeEquals(baseType.asType(), rootEnclosing.asType()) && this == message.getOriginalContainer()) {
-            log.message(message.getKind(), getMessageElement(), getMessageAnnotation(), getMessageAnnotationValue(), message.getText());
-        } else {
+        TypeElement baseEnclosing = Utils.findRootEnclosingType(baseType);
+        if (rootEnclosing == null || !Utils.typeEquals(baseEnclosing.asType(), rootEnclosing.asType())) {
+            // redirect message
             MessageContainer original = message.getOriginalContainer();
-            log.message(message.getKind(), baseType, null, null, wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText()));
+            messageElement = baseType;
+            messageAnnotation = null;
+            messageValue = null;
+            text = wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText());
         }
+
+        TypeElement expectError = context.getTruffleTypes().getExpectError();
+        if (expectError != null) {
+            AnnotationMirror mirror = Utils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError);
+            if (mirror != null) {
+                List<String> expectedTexts = Utils.getAnnotationValueList(String.class, mirror, "value");
+                boolean found = false;
+                for (String expectedText : expectedTexts) {
+                    if (expectedText.endsWith("%") && text.startsWith(expectedText.substring(0, expectedText.length() - 1))) {
+                        found = true;
+                        break;
+                    } else if (text.equals(expectedText)) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    log.message(kind, messageElement, mirror, Utils.getAnnotationValue(mirror, "value"), "Message expected one of '%s' but was '%s'.", expectedTexts, text);
+                } else {
+                    return;
+                }
+
+            }
+        }
+
+        log.message(kind, messageElement, messageAnnotation, messageValue, text);
     }
 
     private static String wrapText(Element element, AnnotationMirror mirror, String text) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/Template.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/Template.java	Tue Sep 10 16:33:28 2013 -0700
@@ -27,7 +27,6 @@
 import javax.lang.model.element.*;
 
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.api.element.*;
 import com.oracle.truffle.dsl.processor.typesystem.*;
 
 public abstract class Template extends MessageContainer {
@@ -36,8 +35,6 @@
     private final String templateMethodName;
     private final AnnotationMirror annotation;
 
-    private List<? extends WritableElement> extensionElements;
-
     public Template(TypeElement templateType, String templateMethodName, AnnotationMirror annotation) {
         this.templateType = templateType;
         this.templateMethodName = templateMethodName;
@@ -68,14 +65,6 @@
         return annotation;
     }
 
-    public List<? extends WritableElement> getExtensionElements() {
-        return extensionElements;
-    }
-
-    public void setExtensionElements(List<? extends WritableElement> extensionMethods) {
-        this.extensionElements = extensionMethods;
-    }
-
     @Override
     public String toString() {
         return getClass().getSimpleName() + "[" + Utils.getSimpleName(getTemplateType()) + "]";
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java	Tue Sep 10 16:33:28 2013 -0700
@@ -43,7 +43,7 @@
     protected final T template;
 
     private boolean emitErrors = true;
-    private boolean parseNullOnError = true;
+    private boolean parseNullOnError = false;
 
     public TemplateMethodParser(ProcessorContext context, T template) {
         this.template = template;
@@ -76,7 +76,7 @@
 
     public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror);
 
-    public abstract E create(TemplateMethod method);
+    public abstract E create(TemplateMethod method, boolean invalid);
 
     public abstract boolean isParsable(ExecutableElement method);
 
@@ -104,7 +104,8 @@
             E parsedMethod = parse(method, mirror);
 
             if (method.getModifiers().contains(Modifier.PRIVATE) && emitErrors) {
-                parsedMethod.addError("Method must not be private.");
+                parsedMethod.addError("Method annotated with @%s must not be private.", getAnnotationType().getSimpleName());
+                parsedMethods.add(parsedMethod);
                 valid = false;
                 continue;
             }
@@ -142,7 +143,7 @@
         ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, false);
         if (returnTypeMirror == null) {
             if (emitErrors) {
-                E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()));
+                E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true);
                 String expectedReturnType = returnTypeSpec.toSignatureString(true);
                 String actualReturnType = Utils.getSimpleName(method.getReturnType());
 
@@ -163,7 +164,7 @@
         List<ActualParameter> parameters = parseParameters(methodSpecification, parameterTypes);
         if (parameters == null) {
             if (isEmitErrors()) {
-                E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()));
+                E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true);
                 String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method),
                                 methodSpecification.toSignatureString(method.getSimpleName().toString()));
                 invalidMethod.addError(message);
@@ -173,7 +174,7 @@
             }
         }
 
-        return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters));
+        return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters), false);
     }
 
     private static String createActualSignature(MethodSpec spec, ExecutableElement method) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardData.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardData.java	Tue Sep 10 16:33:28 2013 -0700
@@ -60,7 +60,7 @@
 
     @Override
     public String toString() {
-        return getMethodName() + getParameters().toString();
+        return (negated ? "!" : "") + getMethodName() + getParameters().toString();
     }
 
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java	Tue Sep 10 16:33:28 2013 -0700
@@ -79,7 +79,7 @@
     }
 
     @Override
-    public GuardData create(TemplateMethod method) {
+    public GuardData create(TemplateMethod method, boolean invalid) {
         GuardData guard = new GuardData(method, specialization, negated);
         /*
          * Update parameters in way that parameter specifications match again the node field names
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastData.java	Tue Sep 10 16:33:28 2013 -0700
@@ -0,0 +1,57 @@
+/*
+ * 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.truffle.dsl.processor.typesystem;
+
+import com.oracle.truffle.dsl.processor.template.*;
+
+public class ImplicitCastData extends TemplateMethod {
+
+    private final TypeData sourceType;
+    private final TypeData targetType;
+
+    public ImplicitCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) {
+        super(method);
+        this.sourceType = sourceType;
+        this.targetType = targetType;
+    }
+
+    public TypeData getSourceType() {
+        return sourceType;
+    }
+
+    public TypeData getTargetType() {
+        return targetType;
+    }
+
+    @Override
+    public int compareTo(TemplateMethod o) {
+        if (o instanceof ImplicitCastData) {
+            // implicit casts are ordered by source type since
+            // its also the order in which they are checked.
+            TypeData otherSourceType = ((ImplicitCastData) o).getSourceType();
+            return this.sourceType.compareTo(otherSourceType);
+        }
+        return super.compareTo(o);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java	Tue Sep 10 16:33:28 2013 -0700
@@ -0,0 +1,75 @@
+/*
+ * 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.truffle.dsl.processor.typesystem;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.template.*;
+
+public class ImplicitCastParser extends TypeSystemMethodParser<ImplicitCastData> {
+
+    public ImplicitCastParser(ProcessorContext context, TypeSystemData typeSystem) {
+        super(context, typeSystem);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return ImplicitCast.class;
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        List<TypeMirror> types = new ArrayList<>();
+        for (TypeData typeData : getTypeSystem().getTypes()) {
+            types.add(typeData.getPrimitiveType());
+        }
+        MethodSpec spec = new MethodSpec(new ParameterSpec("target", types));
+        spec.addRequired(new ParameterSpec("source", types)).setSignature(true);
+        return spec;
+    }
+
+    @Override
+    public ImplicitCastData create(TemplateMethod method, boolean invalid) {
+        if (invalid) {
+            return new ImplicitCastData(method, null, null);
+        }
+
+        ActualParameter target = method.findParameter("targetValue");
+        ActualParameter source = method.findParameter("sourceValue");
+
+        TypeData targetType = target.getTypeSystemType();
+        TypeData sourceType = source.getTypeSystemType();
+
+        if (targetType.equals(sourceType)) {
+            method.addError("Target type and source type of an @%s must not be the same type.", ImplicitCast.class.getSimpleName());
+        }
+
+        return new ImplicitCastData(method, sourceType, targetType);
+    }
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java	Tue Sep 10 16:33:28 2013 -0700
@@ -48,10 +48,25 @@
     }
 
     @Override
-    public TypeCastData create(TemplateMethod method) {
+    public TypeCastData create(TemplateMethod method, boolean invalid) {
+        if (invalid) {
+            return new TypeCastData(method, null, null);
+        }
+
         TypeData targetType = findTypeByMethodName(method, "as");
         ActualParameter parameter = method.findParameter("valueValue");
-        return new TypeCastData(method, parameter.getTypeSystemType(), targetType);
+
+        TypeData sourceType = null;
+        if (parameter != null) {
+            sourceType = getTypeSystem().findTypeData(parameter.getType());
+        }
+        TypeCastData cast = new TypeCastData(method, sourceType, targetType);
+
+        if (targetType != method.getReturnType().getTypeSystemType()) {
+            cast.addError("Cast type %s does not match to the returned type %s.", Utils.getSimpleName(targetType.getPrimitiveType()),
+                            method.getReturnType() != null ? Utils.getSimpleName(method.getReturnType().getTypeSystemType().getPrimitiveType()) : null);
+        }
+        return cast;
     }
 
     @Override
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java	Tue Sep 10 16:33:28 2013 -0700
@@ -48,7 +48,7 @@
     }
 
     @Override
-    public TypeCheckData create(TemplateMethod method) {
+    public TypeCheckData create(TemplateMethod method, boolean invalid) {
         TypeData checkedType = findTypeByMethodName(method, "is");
         assert checkedType != null;
         ActualParameter parameter = method.findParameter("valueValue");
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java	Tue Sep 10 16:33:28 2013 -0700
@@ -44,10 +44,22 @@
         return "is" + Utils.getTypeId(type.getBoxedType());
     }
 
+    public static String isImplicitTypeMethodName(TypeData type) {
+        return "isImplicit" + Utils.getTypeId(type.getBoxedType());
+    }
+
     public static String asTypeMethodName(TypeData type) {
         return "as" + Utils.getTypeId(type.getBoxedType());
     }
 
+    public static String asImplicitTypeMethodName(TypeData type) {
+        return "asImplicit" + Utils.getTypeId(type.getBoxedType());
+    }
+
+    public static String getImplicitClass(TypeData type) {
+        return "getImplicit" + Utils.getTypeId(type.getBoxedType()) + "Class";
+    }
+
     public static String expectTypeMethodName(TypeData type) {
         return "expect" + Utils.getTypeId(type.getBoxedType());
     }
@@ -100,6 +112,20 @@
                             clazz.add(expect);
                         }
                     }
+
+                    CodeExecutableElement asImplicit = createAsImplicitTypeMethod(type);
+                    if (asImplicit != null) {
+                        clazz.add(asImplicit);
+                    }
+                    CodeExecutableElement isImplicit = createIsImplicitTypeMethod(type);
+                    if (isImplicit != null) {
+                        clazz.add(isImplicit);
+                    }
+
+                    CodeExecutableElement typeIndex = createGetTypeIndex(type);
+                    if (typeIndex != null) {
+                        clazz.add(typeIndex);
+                    }
                 }
             }
 
@@ -133,6 +159,95 @@
             return field;
         }
 
+        private CodeExecutableElement createIsImplicitTypeMethod(TypeData type) {
+            TypeSystemData typeSystem = getModel();
+            List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
+            if (casts.isEmpty()) {
+                return null;
+            }
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type));
+            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
+            CodeTreeBuilder builder = method.createBuilder();
+
+            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
+
+            builder.startReturn();
+            String sep = "";
+            for (TypeData sourceType : sourceTypes) {
+                builder.string(sep);
+                builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end();
+                sep = " || ";
+            }
+            builder.end();
+            return method;
+        }
+
+        private CodeExecutableElement createAsImplicitTypeMethod(TypeData type) {
+            TypeSystemData typeSystem = getModel();
+            List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
+            if (casts.isEmpty()) {
+                return null;
+            }
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asImplicitTypeMethodName(type));
+            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
+
+            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
+
+            CodeTreeBuilder builder = method.createBuilder();
+            boolean elseIf = false;
+            for (TypeData sourceType : sourceTypes) {
+                elseIf = builder.startIf(elseIf);
+                builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end();
+                builder.end().startBlock();
+
+                builder.startReturn();
+                ImplicitCastData cast = typeSystem.lookupCast(sourceType, type);
+                if (cast != null) {
+                    builder.startCall(cast.getMethodName());
+                }
+                builder.startCall(asTypeMethodName(sourceType)).string(LOCAL_VALUE).end();
+                if (cast != null) {
+                    builder.end();
+                }
+                builder.end();
+                builder.end();
+            }
+
+            builder.startElseBlock();
+            builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end();
+            builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
+            builder.end();
+            return method;
+        }
+
+        private CodeExecutableElement createGetTypeIndex(TypeData type) {
+            TypeSystemData typeSystem = getModel();
+            List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
+            if (casts.isEmpty()) {
+                return null;
+            }
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(type));
+            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
+
+            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
+            CodeTreeBuilder builder = method.createBuilder();
+            boolean elseIf = false;
+            for (TypeData sourceType : sourceTypes) {
+                elseIf = builder.startIf(elseIf);
+                builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end();
+                builder.end().startBlock();
+                builder.startReturn().typeLiteral(sourceType.getPrimitiveType()).end();
+                builder.end();
+            }
+
+            builder.startElseBlock();
+            builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end();
+            builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
+            builder.end();
+
+            return method;
+        }
+
         private CodeExecutableElement createIsTypeMethod(TypeData type) {
             if (!type.getTypeChecks().isEmpty()) {
                 return null;
@@ -174,8 +289,8 @@
             method.addThrownType(getContext().getTruffleTypes().getUnexpectedValueException());
 
             CodeTreeBuilder body = method.createBuilder();
-            body.startIf().startCall(null, TypeSystemCodeGenerator.isTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end().startBlock();
-            body.startReturn().startCall(null, TypeSystemCodeGenerator.asTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end();
+            body.startIf().startCall(TypeSystemCodeGenerator.isTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end().startBlock();
+            body.startReturn().startCall(TypeSystemCodeGenerator.asTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end();
             body.end(); // if-block
             body.startThrow().startNew(getContext().getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end();
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java	Tue Sep 10 16:33:28 2013 -0700
@@ -36,6 +36,10 @@
     private List<TypeMirror> primitiveTypeMirrors = new ArrayList<>();
     private List<TypeMirror> boxedTypeMirrors = new ArrayList<>();
 
+    private List<ImplicitCastData> implicitCasts;
+    private List<TypeCastData> casts;
+    private List<TypeCheckData> checks;
+
     private TypeMirror genericType;
     private TypeData voidType;
 
@@ -58,6 +62,22 @@
         }
     }
 
+    public void setImplicitCasts(List<ImplicitCastData> implicitCasts) {
+        this.implicitCasts = implicitCasts;
+    }
+
+    public List<ImplicitCastData> getImplicitCasts() {
+        return implicitCasts;
+    }
+
+    public void setCasts(List<TypeCastData> casts) {
+        this.casts = casts;
+    }
+
+    public void setChecks(List<TypeCheckData> checks) {
+        this.checks = checks;
+    }
+
     void setGenericType(TypeMirror genericType) {
         this.genericType = genericType;
     }
@@ -72,6 +92,15 @@
         if (types != null) {
             sinks.addAll(types);
         }
+        if (checks != null) {
+            sinks.addAll(checks);
+        }
+        if (casts != null) {
+            sinks.addAll(casts);
+        }
+        if (implicitCasts != null) {
+            sinks.addAll(implicitCasts);
+        }
         return sinks;
     }
 
@@ -144,4 +173,55 @@
         return getClass().getSimpleName() + "[template = " + Utils.getSimpleName(getTemplateType()) + ", types = " + types + "]";
     }
 
+    public Set<TypeData> lookupCastSourceTypes() {
+        if (getImplicitCasts() == null) {
+            return null;
+        }
+
+        Set<TypeData> sourceTypes = new TreeSet<>();
+        for (ImplicitCastData cast : getImplicitCasts()) {
+            sourceTypes.add(cast.getSourceType());
+        }
+        return sourceTypes;
+    }
+
+    public List<ImplicitCastData> lookupByTargetType(TypeData targetType) {
+        if (getImplicitCasts() == null) {
+            return Collections.emptyList();
+        }
+        List<ImplicitCastData> foundCasts = new ArrayList<>();
+        for (ImplicitCastData cast : getImplicitCasts()) {
+            if (cast.getTargetType().equals(targetType)) {
+                foundCasts.add(cast);
+            }
+        }
+        return foundCasts;
+    }
+
+    public ImplicitCastData lookupCast(TypeData sourceType, TypeData targetType) {
+        if (getImplicitCasts() == null) {
+            return null;
+        }
+        for (ImplicitCastData cast : getImplicitCasts()) {
+            if (cast.getSourceType().equals(sourceType) && cast.getTargetType().equals(targetType)) {
+                return cast;
+            }
+        }
+        return null;
+    }
+
+    public List<TypeData> lookupSourceTypes(TypeData type) {
+        List<TypeData> sourceTypes = new ArrayList<>();
+        sourceTypes.add(type);
+        if (getImplicitCasts() != null) {
+            for (ImplicitCastData cast : getImplicitCasts()) {
+                if (cast.getTargetType() == type) {
+                    sourceTypes.add(cast.getSourceType());
+                }
+            }
+        }
+        Collections.sort(sourceTypes);
+        return sourceTypes;
+    }
+
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java	Tue Sep 10 16:33:28 2013 -0700
@@ -37,7 +37,7 @@
 
 public class TypeSystemParser extends TemplateParser<TypeSystemData> {
 
-    public static final List<Class<TypeSystem>> ANNOTATIONS = Arrays.asList(TypeSystem.class);
+    public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(TypeSystem.class, ExpectError.class);
 
     public TypeSystemParser(ProcessorContext c) {
         super(c);
@@ -71,7 +71,7 @@
         }
 
         typeSystem.setTypes(parseTypes(typeSystem));
-        if (typeSystem.getTypes() == null) {
+        if (typeSystem.hasErrors()) {
             return typeSystem;
         }
 
@@ -84,11 +84,19 @@
         verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class);
 
         List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType));
-
+        List<ImplicitCastData> implicitCasts = new ImplicitCastParser(context, typeSystem).parse(elements);
         List<TypeCastData> casts = new TypeCastParser(context, typeSystem).parse(elements);
         List<TypeCheckData> checks = new TypeCheckParser(context, typeSystem).parse(elements);
 
-        if (casts == null || checks == null) {
+        if (casts == null || checks == null || implicitCasts == null) {
+            return typeSystem;
+        }
+
+        typeSystem.setImplicitCasts(implicitCasts);
+        typeSystem.setCasts(casts);
+        typeSystem.setChecks(checks);
+
+        if (typeSystem.hasErrors()) {
             return typeSystem;
         }
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java	Tue Sep 10 16:32:27 2013 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java	Tue Sep 10 16:33:28 2013 -0700
@@ -69,4 +69,9 @@
     public boolean isBigInteger(@SuppressWarnings("unused") int value) {
         return true;
     }
+
+    @ImplicitCast
+    public BigInteger castBigInteger(int value) {
+        return BigInteger.valueOf(value);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mx/.pylintrc	Tue Sep 10 16:33:28 2013 -0700
@@ -0,0 +1,278 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Pickle collected data for later comparisons.
+persistent=no
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time. See also the "--disable" option for examples.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once).You can also use "--disable=all" to
+# disable everything first and then reenable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use"--disable=all --enable=classes
+# --disable=W"
+disable=attribute-defined-outside-init,arguments-differ,
+        bare-except,global-statement,protected-access,redefined-outer-name,
+        unused-argument,star-args,pointless-string-statement,old-style-class,
+        too-many-lines,missing-docstring,no-init,no-self-use,too-many-statements,
+        too-many-locals,too-few-public-methods,too-many-instance-attributes,
+        too-many-arguments,too-many-branches,too-many-public-methods,
+        abstract-method
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html. You can also give a reporter class, eg
+# mypackage.mymodule.MyReporterClass.
+output-format=text
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=no
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (RP0004).
+comment=no
+
+# Template used to display messages. This is a python new-style format string
+# used to format the massage information. See doc for all details
+#msg-template=
+
+
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=filter,apply,input
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=[a-zA-Z0-9_]{2,30}$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z_][a-zA-Z0-9_]{1,40}$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-z_][a-zA-Z0-9_]{2,40}$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-zA-Z0-9_]{1,30}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-zA-Z0-9_]{0,30}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-zA-Z0-9_]{0,30}$
+
+# Regular expression which should only match correct attribute names in class
+# bodies
+class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=.*
+
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=-1
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=300
+
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=^\s*(# )?<?https?://\S+>?$
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string='    '
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+# Ignore imports when computing similarities.
+ignore-imports=no
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set).
+ignored-classes=SQLObject
+
+# When zope mode is activated, add a predefined set of Zope acquired attributes
+# to generated-members.
+zope=no
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=REQUEST,acl_users,aq_parent
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the beginning of the name of dummy variables
+# (i.e. not used).
+dummy-variables-rgx=_$|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=mcs
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branches=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
--- a/mx/commands.py	Tue Sep 10 16:32:27 2013 -0700
+++ b/mx/commands.py	Tue Sep 10 16:33:28 2013 -0700
@@ -45,10 +45,10 @@
 _vmChoices = {
     'graal' : 'All compilation is performed with Graal. This includes bootstrapping Graal itself unless -XX:-BootstrapGraal is used.',
     'server' : 'Normal compilation is performed with the tiered system (i.e., client + server), Truffle compilation is performed with Graal. Use this for optimal Truffle performance.',
-    'client' : None, # normal compilation with client compiler, explicit compilation (e.g., by Truffle) with Graal
-    'server-nograal' : None, # all compilation with tiered system (i.e., client + server), Graal omitted
-    'client-nograal' : None, # all compilation with client compiler, Graal omitted
-    'original' : None, # default VM copied from bootstrap JDK
+    'client' : None,  # normal compilation with client compiler, explicit compilation (e.g., by Truffle) with Graal
+    'server-nograal' : None,  # all compilation with tiered system (i.e., client + server), Graal omitted
+    'client-nograal' : None,  # all compilation with client compiler, Graal omitted
+    'original' : None,  # default VM copied from bootstrap JDK
 }
 
 """ The VM that will be run by the 'vm' command and built by default by the 'build' command.
@@ -95,14 +95,13 @@
         items = [k for k in _vmChoices.keys() if _vmChoices[k] is not None]
         descriptions = [_vmChoices[k] for k in _vmChoices.keys() if _vmChoices[k] is not None]
         vm = mx.select_items(items, descriptions, allowMultiple=False)
-        answer = raw_input('Persist this choice by adding "DEFAULT_VM=' + vm + '" to ' + envPath + '? [Yn]: ')
-        if not answer.lower().startswith('n'):
+        if mx.ask_yes_no('Persist this choice by adding "DEFAULT_VM=' + vm + '" to ' + envPath, 'y'):
             with open(envPath, 'a') as fp:
                 print >> fp, 'DEFAULT_VM=' + vm
     _vm = vm
     return vm
 
-""" 
+"""
 A context manager that can be used with the 'with' statement to set the VM
 used by all VM executions within the scope of the 'with' statement. For example:
 
@@ -117,17 +116,17 @@
         self.build = build if build else _vmbuild
         self.previousVm = _vm
         self.previousBuild = _vmbuild
-        
+
     def __enter__(self):
         global _vm, _vmbuild
         _vm = self.vm
         _vmbuild = self.build
-        
+
     def __exit__(self, exc_type, exc_value, traceback):
         global _vm, _vmbuild
         _vm = self.previousVm
         _vmbuild = self.previousBuild
-    
+
 def _chmodDir(chmodFlags, dirname, fnames):
     os.chmod(dirname, chmodFlags)
     for name in fnames:
@@ -145,7 +144,7 @@
                 shutil.rmtree(name)
             elif os.path.isfile(name):
                 os.unlink(name)
-                
+
         rmIfExists(join(_graal_home, 'build'))
         rmIfExists(join(_graal_home, 'build-nograal'))
         rmIfExists(_jdksDir())
@@ -154,7 +153,7 @@
 def export(args):
     """create a GraalVM zip file for distribution"""
 
-    parser = ArgumentParser(prog='mx export');
+    parser = ArgumentParser(prog='mx export')
     parser.add_argument('--omit-vm-build', action='store_false', dest='vmbuild', help='omit VM build step')
     parser.add_argument('--omit-dist-init', action='store_false', dest='distInit', help='omit class files and IDE configurations from distribution')
     parser.add_argument('zipfile', nargs=REMAINDER, metavar='zipfile')
@@ -201,13 +200,13 @@
     vmOpts, benchmarksAndOptions = _extract_VM_args(args, useDoubleDash=availableBenchmarks is None)
 
     if availableBenchmarks is None:
-        harnessArgs = benchmarksAndOptions 
+        harnessArgs = benchmarksAndOptions
         return runBenchmark(None, harnessArgs, vmOpts)
 
     if len(benchmarksAndOptions) == 0:
         mx.abort('at least one benchmark name or "all" must be specified')
     benchmarks = list(itertools.takewhile(lambda x: not x.startswith('-'), benchmarksAndOptions))
-    harnessArgs = benchmarksAndOptions[len(benchmarks):] 
+    harnessArgs = benchmarksAndOptions[len(benchmarks):]
 
     if 'all' in benchmarks:
         benchmarks = availableBenchmarks
@@ -229,7 +228,7 @@
 
     def launcher(bm, harnessArgs, extraVmOpts):
         return sanitycheck.getDacapo(bm, harnessArgs).test(_get_vm(), extraVmOpts=extraVmOpts)
-        
+
     _run_benchmark(args, sanitycheck.dacapoSanityWarmup.keys(), launcher)
 
 def scaladacapo(args):
@@ -281,12 +280,11 @@
 def _handle_missing_VM(bld, vm):
     mx.log('The ' + bld + ' ' + vm + ' VM has not been created')
     if sys.stdout.isatty():
-        answer = raw_input('Build it now? [Yn]: ')
-        if not answer.lower().startswith('n'):
+        if mx.ask_yes_no('Build it now', 'y'):
             with VM(vm, bld):
                 build([])
             return
-    mx.abort('You need to run "mx --vm ' + vm + '--vmbuild ' + bld + ' build" to build the selected VM')
+    mx.abort('You need to run "mx --vm ' + vm + ' --vmbuild ' + bld + ' build" to build the selected VM')
 
 def _jdk(build='product', vmToCheck=None, create=False, installGraalJar=True):
     """
@@ -334,7 +332,7 @@
             if mx.get_os() != 'windows':
                 chmodRecursive(jdk, 0755)
             shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), 'original'))
-            
+
 
             with open(jvmCfg, 'w') as fp:
                 for line in jvmCfgLines:
@@ -350,10 +348,10 @@
             if _installed_jdks and mx._opts.verbose:
                 mx.log("Could not find JDK directory at " + jdk)
             _handle_missing_VM(build, vmToCheck if vmToCheck else 'graal')
-            
+
     if installGraalJar:
         _installGraalJarInJdks(mx.distribution('GRAAL'))
-    
+
     if vmToCheck is not None:
         jvmCfg = _vmCfgInJdk(jdk)
         found = False
@@ -364,7 +362,7 @@
                     break
         if not found:
             _handle_missing_VM(build, vmToCheck)
-        
+
     return jdk
 
 def _installGraalJarInJdks(graalDist):
@@ -380,25 +378,27 @@
                 shutil.copyfile(graalJar, tmp)
                 os.close(fd)
                 shutil.move(tmp, join(jreLibDir, 'graal.jar'))
-                
+
                 if exists(graalOptions):
                     shutil.copy(graalOptions, join(jreLibDir, 'graal.options'))
 
 # run a command in the windows SDK Debug Shell
-def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo={}):
+def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None):
+    if respondTo is None:
+        respondTo = {}
     newLine = os.linesep
-    STARTTOKEN = 'RUNINDEBUGSHELL_STARTSEQUENCE'
-    ENDTOKEN = 'RUNINDEBUGSHELL_ENDSEQUENCE'
+    startToken = 'RUNINDEBUGSHELL_STARTSEQUENCE'
+    endToken = 'RUNINDEBUGSHELL_ENDSEQUENCE'
 
     winSDK = mx.get_env('WIN_SDK', 'C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\')
-    
+
     if not exists(winSDK):
         mx.abort("Could not find Windows SDK : '" + winSDK + "' does not exist")
-        
+
     if not exists(join(winSDK, 'Bin', 'SetEnv.cmd')):
         mx.abort("Invalid Windows SDK path (" + winSDK + ") : could not find Bin/SetEnv.cmd (you can use the WIN_SDK environment variable to specify an other path)")
 
-    p = subprocess.Popen('cmd.exe /E:ON /V:ON /K ""' + winSDK + '/Bin/SetEnv.cmd" & echo ' + STARTTOKEN + '"', \
+    p = subprocess.Popen('cmd.exe /E:ON /V:ON /K ""' + winSDK + '/Bin/SetEnv.cmd" & echo ' + startToken + '"', \
             shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
     stdout = p.stdout
     stdin = p.stdin
@@ -406,20 +406,20 @@
         log = open(logFile, 'w')
     ret = False
     while True:
-        
+
         # encoding may be None on windows plattforms
         if sys.stdout.encoding is None:
             encoding = 'utf-8'
         else:
             encoding = sys.stdout.encoding
-        
+
         line = stdout.readline().decode(encoding)
         if logFile:
             log.write(line.encode('utf-8'))
         line = line.strip()
         mx.log(line)
-        if line == STARTTOKEN:
-            stdin.write('cd /D ' + workingDir + ' & ' + cmd + ' & echo ' + ENDTOKEN + newLine)
+        if line == startToken:
+            stdin.write('cd /D ' + workingDir + ' & ' + cmd + ' & echo ' + endToken + newLine)
         for regex in respondTo.keys():
             match = regex.search(line)
             if match:
@@ -428,7 +428,7 @@
             match = findInOutput.search(line)
             if match:
                 ret = True
-        if line == ENDTOKEN:
+        if line == endToken:
             if not findInOutput:
                 stdin.write('echo ERRXXX%errorlevel%' + newLine)
             else:
@@ -436,12 +436,44 @@
         if line.startswith('ERRXXX'):
             if line == 'ERRXXX0':
                 ret = True
-            break;
+            break
     stdin.write('exit' + newLine)
     if logFile:
         log.close()
     return ret
 
+def pylint(args):
+    """run pylint (if available) over Python source files"""
+    rcfile = join(_graal_home, 'mx', '.pylintrc')
+    if not exists(rcfile):
+        mx.log('pylint configuration file does not exist: ' + rcfile)
+        return
+
+    try:
+        output = subprocess.check_output(['pylint', '--version'], stderr=subprocess.STDOUT)
+        m = re.match(r'.*pylint (\d+)\.(\d+)\.(\d+).*', output, re.DOTALL)
+        if not m:
+            mx.log('could not determine pylint version from ' + output)
+            return
+        major, minor, micro = (int(m.group(1)), int(m.group(2)), int(m.group(3)))
+        if major < 1:
+            mx.log('require pylint version >= 1 (got {0}.{1}.{2})'.format(major, minor, micro))
+            return
+    except BaseException:
+        mx.log('pylint is not available')
+        return
+
+
+    env = os.environ.copy()
+    env['PYTHONPATH'] = dirname(mx.__file__)
+
+    versioned = subprocess.check_output(['hg', 'locate', '-f'], stderr=subprocess.STDOUT).split(os.linesep)
+    for f in versioned:
+        if f.endswith('.py'):
+            pyfile = f
+            mx.log('Running pylint on ' + pyfile + '...')
+            mx.run(['pylint', '--reports=n', '--rcfile=' + rcfile, pyfile], env=env)
+
 def jdkhome(args, vm=None):
     """print the JDK directory selected for the 'vm' command"""
 
@@ -458,16 +490,16 @@
         'INSTALL' : 'Install the built VM into the JDK? (default: y)',
         'ZIP_DEBUGINFO_FILES' : 'Install zipped debug symbols file? (default: 0)',
     }
-    
+
     mx.log('HotSpot build variables that can be set by the -D option to "mx build":')
     mx.log('')
     for n in sorted(buildVars.iterkeys()):
         mx.log(n)
         mx.log(textwrap.fill(buildVars[n], initial_indent='    ', subsequent_indent='    ', width=200))
-        
+
     mx.log('')
     mx.log('Note that these variables can be given persistent values in the file ' + join(_graal_home, 'mx', 'env') + ' (see \'mx about\').')
-    
+
 def build(args, vm=None):
     """build the VM binary
 
@@ -488,7 +520,7 @@
             return result
 
     # Call mx.build to compile the Java sources
-    parser=AP()
+    parser = AP()
     parser.add_argument('--export-dir', help='directory to which graal.jar and graal.options will be copied', metavar='<path>')
     parser.add_argument('-D', action='append', help='set a HotSpot build variable (run \'mx buildvars\' to list variables)', metavar='name=value')
     opts2 = mx.build(['--source', '1.7'] + args, parser=parser)
@@ -522,7 +554,11 @@
     else:
         assert vm == 'graal', vm
         buildSuffix = 'graal'
-        
+
+    if _installed_jdks and _installed_jdks != _graal_home:
+        if not mx.ask_yes_no("Warning: building while --installed-jdks is set (" + _installed_jdks + ") is not recommanded - are you sure you want to continue", 'n'):
+            mx.abort(1)
+
     for build in builds:
         if build == 'ide-build-target':
             build = os.environ.get('IDE_BUILD_TARGET', None)
@@ -577,7 +613,7 @@
             variant = {'client': 'compiler1', 'server': 'compiler2'}.get(vm, vm)
             project_config = variant + '_' + build
             _runInDebugShell('msbuild ' + _graal_home + r'\build\vs-amd64\jvm.vcproj /p:Configuration=' + project_config + ' /target:clean', _graal_home)
-            winCompileCmd = r'set HotSpotMksHome=' + mksHome + r'& set OUT_DIR=' + jdk + r'& set JAVA_HOME=' + jdk + r'& set path=%JAVA_HOME%\bin;%path%;%HotSpotMksHome%& cd /D "' +_graal_home + r'\make\windows"& call create.bat ' + _graal_home
+            winCompileCmd = r'set HotSpotMksHome=' + mksHome + r'& set OUT_DIR=' + jdk + r'& set JAVA_HOME=' + jdk + r'& set path=%JAVA_HOME%\bin;%path%;%HotSpotMksHome%& cd /D "' + _graal_home + r'\make\windows"& call create.bat ' + _graal_home
             print(winCompileCmd)
             winCompileSuccess = re.compile(r"^Writing \.vcxproj file:")
             if not _runInDebugShell(winCompileCmd, _graal_home, compilelogfile, winCompileSuccess):
@@ -590,14 +626,14 @@
         else:
             cpus = multiprocessing.cpu_count()
             runCmd = [mx.gmake_cmd()]
-            runCmd.append(build + buildSuffix) 
+            runCmd.append(build + buildSuffix)
             env = os.environ.copy()
-            
+
             if opts2.D:
                 for nv in opts2.D:
                     name, value = nv.split('=', 1)
                     env[name.strip()] = value
-            
+
             env.setdefault('ARCH_DATA_MODEL', '64')
             env.setdefault('LANG', 'C')
             env.setdefault('HOTSPOT_BUILD_JOBS', str(cpus))
@@ -645,7 +681,7 @@
                 if line.strip() == vmKnown.strip():
                     found = True
                 lines.append(line)
-                
+
         if not found:
             mx.log('Appending "' + prefix + 'KNOWN" to ' + jvmCfg)
             if mx.get_os() != 'windows':
@@ -699,7 +735,7 @@
         for p in mx.projects():
             excludes += _find_classes_with_annotations(p, None, ['@Snippet', '@ClassSubstitution', '@Test'], includeInnerClasses=True).keys()
             excludes += p.find_classes_with_matching_source_line(None, lambda line: 'JaCoCo Exclude' in line, includeInnerClasses=True).keys()
-            
+
         includes = ['com.oracle.graal.*']
         agentOptions = {
                         'append' : 'true' if _jacoco == 'append' else 'false',
@@ -714,12 +750,12 @@
 
     exe = join(jdk, 'bin', mx.exe_suffix('java'))
     pfx = _vm_prefix.split() if _vm_prefix is not None else []
-    
+
     if '-version' in args:
-        ignoredArgs = args[args.index('-version')+1:]
+        ignoredArgs = args[args.index('-version') + 1:]
         if  len(ignoredArgs) > 0:
             mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs))
-    
+
     return mx.run(pfx + [exe, '-' + vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout)
 
 def _find_classes_with_annotations(p, pkgRoot, annotations, includeInnerClasses=False):
@@ -728,7 +764,7 @@
     (ignoring preceding whitespace) and return the fully qualified class name for each Java
     source file matched in a list.
     """
-    
+
     matches = lambda line : len([a for a in annotations if line == a or line.startswith(a + '(')]) != 0
     return p.find_classes_with_matching_source_line(pkgRoot, matches, includeInnerClasses)
 
@@ -740,7 +776,7 @@
         if useDoubleDash:
             if args[i] == '--':
                 vmArgs = args[:i]
-                remainder = args[i + 1:] 
+                remainder = args[i + 1:]
                 return vmArgs, remainder
         else:
             if not args[i].startswith('-'):
@@ -750,25 +786,19 @@
                     else:
                         continue
                 vmArgs = args[:i]
-                remainder = args[i:] 
+                remainder = args[i:]
                 return vmArgs, remainder
-            
+
     return args, []
-    
+
 def _run_tests(args, harness, annotations, testfile):
-    
-    
+
+
     vmArgs, tests = _extract_VM_args(args)
     for t in tests:
         if t.startswith('-'):
             mx.abort('VM option ' + t + ' must precede ' + tests[0])
 
-    def containsAny(c, substrings):
-        for s in substrings:
-            if s in c:
-                return True
-        return False
-    
     candidates = []
     for p in mx.projects():
         if mx.java().javaCompliance < p.javaCompliance:
@@ -833,14 +863,14 @@
 
     If filters are supplied, only tests whose fully qualified name
     includes a filter as a substring are run.
-    
+
     For example, this command line:
-    
+
        mx unittest -G:Dump= -G:MethodFilter=BC_aload.* -G:+PrintCFG BC_aload
-    
+
     will run all JUnit test classes that contain 'BC_aload' in their
-    fully qualified name and will pass these options to the VM: 
-    
+    fully qualified name and will pass these options to the VM:
+
         -G:Dump= -G:MethodFilter=BC_aload.* -G:+PrintCFG
 
     To get around command line length limitations on some OSes, the
@@ -853,7 +883,7 @@
     As with all other commands, using the global '-v' before 'unittest'
     command will cause mx to show the complete command line
     it uses to run the VM.
-""" 
+"""
 
 def unittest(args):
     """run the JUnit tests (all testcases){0}"""
@@ -875,8 +905,8 @@
 
     vmsDefault = ','.join(_vmChoices.keys())
     vmbuildsDefault = ','.join(_vmbuildChoices)
-    
-    parser = ArgumentParser(prog='mx buildvms');
+
+    parser = ArgumentParser(prog='mx buildvms')
     parser.add_argument('--vms', help='a comma separated list of VMs to build (default: ' + vmsDefault + ')', metavar='<args>', default=vmsDefault)
     parser.add_argument('--builds', help='a comma separated list of build types (default: ' + vmbuildsDefault + ')', metavar='<args>', default=vmbuildsDefault)
     parser.add_argument('-n', '--no-check', action='store_true', help='omit running "java -version" after each build')
@@ -897,7 +927,8 @@
                 start = time.time()
                 mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')')
                 # Run as subprocess so that output can be directed to a file
-                subprocess.check_call([sys.executable, '-u', join('mxtool', 'mx.py'), '--vm', v, '--vmbuild', vmbuild, 'build'], cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT)
+                subprocess.check_call([sys.executable, '-u', join('mxtool', 'mx.py'), '--vm', v, '--vmbuild',
+                                       vmbuild, 'build'], cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT)
                 duration = datetime.timedelta(seconds=time.time() - start)
                 mx.log('END:   ' + v + '-' + vmbuild + '\t[' + str(duration) + ']')
             else:
@@ -936,7 +967,7 @@
             mx.abort(codeOrMessage)
             return self
 
-    parser = ArgumentParser(prog='mx gate');
+    parser = ArgumentParser(prog='mx gate')
     parser.add_argument('-j', '--omit-java-clean', action='store_false', dest='cleanJava', help='omit cleaning Java native code')
     parser.add_argument('-n', '--omit-native-clean', action='store_false', dest='cleanNative', help='omit cleaning and building native code')
     parser.add_argument('-g', '--only-build-graalvm', action='store_false', dest='buildNonGraal', help='only build the Graal VM')
@@ -945,11 +976,15 @@
     args = parser.parse_args(args)
 
     global _jacoco
-    
+
     tasks = []
     total = Task('Gate')
     try:
 
+        t = Task('Pylint')
+        pylint([])
+        tasks.append(t.stop())
+
         t = Task('Clean')
         cleanArgs = []
         if not args.cleanNative:
@@ -976,7 +1011,7 @@
         if mx.canonicalizeprojects([]) != 0:
             t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/projects files.')
         tasks.append(t.stop())
-        
+
         t = Task('BuildJava')
         build(['--no-native', '--jdt-warning-as-error'])
         tasks.append(t.stop())
@@ -985,10 +1020,10 @@
         if mx.checkstyle([]) != 0:
             t.abort('Checkstyle warnings were found')
         tasks.append(t.stop())
-        
+
         if exists('jacoco.exec'):
             os.unlink('jacoco.exec')
-        
+
         if args.jacocout is not None:
             _jacoco = 'append'
         else:
@@ -1007,10 +1042,10 @@
             t = Task('BootstrapWithGCVerification:product')
             vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'])
             tasks.append(t.stop())
-    
+
         with VM('graal', 'product'):
             t = Task('BootstrapWithG1GCVerification:product')
-            vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC','-XX:+UseG1GC','-XX:+UseNewCode','-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'])
+            vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+UseNewCode', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'])
             tasks.append(t.stop())
 
         with VM('graal', 'product'):
@@ -1023,7 +1058,7 @@
             vm(['-G:+AOTCompilation', '-G:+VerifyPhases', '-esa', '-version'])
             tasks.append(t.stop())
 
-        with VM('server', 'product'): # hosted mode
+        with VM('server', 'product'):  # hosted mode
             t = Task('UnitTests:hosted-product')
             unittest([])
             tasks.append(t.stop())
@@ -1037,7 +1072,7 @@
 
         if args.jacocout is not None:
             jacocoreport([args.jacocout])
-            
+
         _jacoco = 'off'
 
         t = Task('CleanAndBuildGraalVisualizer')
@@ -1058,7 +1093,7 @@
                         t = Task('DaCapo_pmd:' + theVm + ':' + vmbuild)
                         dacapo(['pmd'])
                         tasks.append(t.stop())
-    
+
                         t = Task('UnitTests:' + theVm + ':' + vmbuild)
                         unittest(['-XX:CompileCommand=exclude,*::run*', 'graal.api'])
                         tasks.append(t.stop())
@@ -1078,7 +1113,7 @@
         mx.log('  ' + str(t.duration) + '\t' + t.title)
     mx.log('  =======')
     mx.log('  ' + str(total.duration))
-    
+
 def deoptalot(args):
     """bootstrap a fastdebug Graal VM with DeoptimizeALot and VerifyOops on
 
@@ -1088,15 +1123,15 @@
     if len(args) > 0 and args[0].isdigit():
         count = int(args[0])
         del args[0]
-    
+
     for _ in range(count):
         if not vm(['-XX:+DeoptimizeALot', '-XX:+VerifyOops'] + args + ['-version'], vmbuild='fastdebug') == 0:
             mx.abort("Failed")
-            
+
 def longtests(args):
-    
+
     deoptalot(['15', '-Xmx48m'])
-    
+
     dacapo(['100', 'eclipse', '-esa'])
 
 def gv(args):
@@ -1131,7 +1166,7 @@
     vm = _get_vm()
     if len(args) is 0:
         args = ['all']
-    
+
     vmArgs = [arg for arg in args if arg.startswith('-')]
 
     def benchmarks_in_group(group):
@@ -1140,7 +1175,7 @@
 
     results = {}
     benchmarks = []
-    #DaCapo
+    # DaCapo
     if ('dacapo' in args or 'all' in args):
         benchmarks += sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Benchmark)
     else:
@@ -1163,23 +1198,23 @@
             if (iterations > 0):
                 benchmarks += [sanitycheck.getScalaDacapo(scaladacapo, ['-n', str(iterations)])]
 
-    #Bootstrap
+    # Bootstrap
     if ('bootstrap' in args or 'all' in args):
         benchmarks += sanitycheck.getBootstraps()
-    #SPECjvm2008
+    # SPECjvm2008
     if ('specjvm2008' in args or 'all' in args):
         benchmarks += [sanitycheck.getSPECjvm2008(['-ikv', '-wt', '120', '-it', '120'])]
     else:
         specjvms = benchmarks_in_group('specjvm2008')
         for specjvm in specjvms:
             benchmarks += [sanitycheck.getSPECjvm2008(['-ikv', '-wt', '120', '-it', '120', specjvm])]
-            
+
     if ('specjbb2005' in args or 'all' in args):
         benchmarks += [sanitycheck.getSPECjbb2005()]
-        
-    if ('specjbb2013' in args): # or 'all' in args //currently not in default set
+
+    if ('specjbb2013' in args):  # or 'all' in args //currently not in default set
         benchmarks += [sanitycheck.getSPECjbb2013()]
-        
+
     if ('ctw-full' in args):
         benchmarks.append(sanitycheck.getCTW(vm, sanitycheck.CTWMode.Full))
     if ('ctw-noinline' in args):
@@ -1198,37 +1233,36 @@
 
 def specjvm2008(args):
     """run one or more SPECjvm2008 benchmarks"""
-    
+
     def launcher(bm, harnessArgs, extraVmOpts):
         return sanitycheck.getSPECjvm2008(harnessArgs + [bm]).bench(_get_vm(), extraVmOpts=extraVmOpts)
-    
+
     availableBenchmarks = set(sanitycheck.specjvm2008Names)
     for name in sanitycheck.specjvm2008Names:
         parts = name.rsplit('.', 1)
         if len(parts) > 1:
             assert len(parts) == 2
             group = parts[0]
-            print group
             availableBenchmarks.add(group)
 
     _run_benchmark(args, sorted(availableBenchmarks), launcher)
-    
+
 def specjbb2013(args):
     """runs the composite SPECjbb2013 benchmark"""
-    
+
     def launcher(bm, harnessArgs, extraVmOpts):
         assert bm is None
         return sanitycheck.getSPECjbb2013(harnessArgs).bench(_get_vm(), extraVmOpts=extraVmOpts)
-    
+
     _run_benchmark(args, None, launcher)
 
 def specjbb2005(args):
     """runs the composite SPECjbb2005 benchmark"""
-    
+
     def launcher(bm, harnessArgs, extraVmOpts):
         assert bm is None
         return sanitycheck.getSPECjbb2005(harnessArgs).bench(_get_vm(), extraVmOpts=extraVmOpts)
-    
+
     _run_benchmark(args, None, launcher)
 
 def hsdis(args, copyToDir=None):
@@ -1252,17 +1286,17 @@
     Run a tool over the input files to convert all embedded HexCodeFiles
     to a disassembled format."""
 
-    parser = ArgumentParser(prog='mx hcfdis');
+    parser = ArgumentParser(prog='mx hcfdis')
     parser.add_argument('-m', '--map', help='address to symbol map applied to disassembler output')
     parser.add_argument('files', nargs=REMAINDER, metavar='files...')
 
     args = parser.parse_args(args)
-    
+
     path = join(_graal_home, 'lib', 'hcfdis-1.jar')
     if not exists(path):
         mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hcfdis-1.jar'])
     mx.run_java(['-jar', path] + args.files)
-    
+
     if args.map is not None:
         addressRE = re.compile(r'0[xX]([A-Fa-f0-9]+)')
         with open(args.map) as fp:
@@ -1271,8 +1305,8 @@
         for l in lines:
             addressAndSymbol = l.split(' ', 1)
             if len(addressAndSymbol) == 2:
-                address, symbol = addressAndSymbol;
-                if address.startswith('0x'): 
+                address, symbol = addressAndSymbol
+                if address.startswith('0x'):
                     address = long(address, 16)
                     symbols[address] = symbol
         for f in args.files:
@@ -1334,6 +1368,7 @@
         'hcfdis': [hcfdis, ''],
         'igv' : [igv, ''],
         'jdkhome': [jdkhome, ''],
+        'pylint': [pylint, ''],
         'dacapo': [dacapo, '[VM options] benchmarks...|"all" [DaCapo options]'],
         'scaladacapo': [scaladacapo, '[VM options] benchmarks...|"all" [Scala DaCapo options]'],
         'specjvm2008': [specjvm2008, '[VM options] benchmarks...|"all" [SPECjvm2008 options]'],
@@ -1358,11 +1393,11 @@
     mx.add_argument('--vmcwd', dest='vm_cwd', help='current directory will be changed to <path> before the VM is executed', default=None, metavar='<path>')
     mx.add_argument('--installed-jdks', help='the base directory in which the JDKs cloned from $JAVA_HOME exist. ' +
                     'The VM selected by --vm and --vmbuild options is under this directory (i.e., ' +
-                    join('<path>', '<vmbuild>', 'jre', 'lib', '<vm>', mx.add_lib_prefix(mx.add_lib_suffix('jvm'))) + ')', default=None, metavar='<path>')
+                    join('<path>', '<jdk-version>', '<vmbuild>', 'jre', 'lib', '<vm>', mx.add_lib_prefix(mx.add_lib_suffix('jvm'))) + ')', default=None, metavar='<path>')
 
     if (_vmSourcesAvailable):
         mx.add_argument('--vm', action='store', dest='vm', choices=_vmChoices.keys(), help='the VM type to build/run')
-        mx.add_argument('--vmbuild', action='store', dest='vmbuild', choices=_vmbuildChoices, help='the VM build to build/run (default: ' + _vmbuildChoices[0] +')')
+        mx.add_argument('--vmbuild', action='store', dest='vmbuild', choices=_vmbuildChoices, help='the VM build to build/run (default: ' + _vmbuildChoices[0] + ')')
         mx.add_argument('--ecl', action='store_true', dest='make_eclipse_launch', help='create launch configuration for running VM execution(s) in Eclipse')
         mx.add_argument('--vmprefix', action='store', dest='vm_prefix', help='prefix for running the VM (e.g. "/usr/bin/gdb --args")', metavar='<prefix>')
         mx.add_argument('--gdb', action='store_const', const='/usr/bin/gdb --args', dest='vm_prefix', help='alias for --vmprefix "/usr/bin/gdb --args"')
@@ -1371,9 +1406,9 @@
             'export': [export, '[-options] [zipfile]'],
         })
 
-    mx.commands.update(commands)
+    mx._commands.update(commands)
 
-def mx_post_parse_cmd_line(opts):#
+def mx_post_parse_cmd_line(opts):  #
     # TODO _minVersion check could probably be part of a Suite in mx?
     if (mx.java().version < _minVersion) :
         mx.abort('Requires Java version ' + str(_minVersion) + ' or greater, got version ' + str(mx.java().version))
--- a/mx/outputparser.py	Tue Sep 10 16:32:27 2013 -0700
+++ b/mx/outputparser.py	Tue Sep 10 16:33:28 2013 -0700
@@ -26,13 +26,13 @@
 import re
 
 class OutputParser:
-    
+
     def __init__(self):
         self.matchers = []
-        
+
     def addMatcher(self, matcher):
         self.matchers.append(matcher)
-    
+
     def parse(self, output):
         valueMaps = []
         for matcher in self.matchers:
@@ -47,12 +47,12 @@
 given as the group name enclosed in '<' and '>'.
 """
 class ValuesMatcher:
-    
+
     def __init__(self, regex, valuesTemplate):
         assert isinstance(valuesTemplate, dict)
         self.regex = regex
         self.valuesTemplate = valuesTemplate
-        
+
     def parse(self, text, valueMaps):
         for match in self.regex.finditer(text):
             valueMap = {}
@@ -62,10 +62,10 @@
                 assert not valueMap.has_key(key), key
                 valueMap[key] = value
             valueMaps.append(valueMap)
-        
+
     def get_template_value(self, match, template):
         def replace_var(m):
             groupName = m.group(1)
             return match.group(groupName)
-        
+
         return re.sub(r'<([\w]+)>', replace_var, template)
--- a/mx/projects	Tue Sep 10 16:32:27 2013 -0700
+++ b/mx/projects	Tue Sep 10 16:33:28 2013 -0700
@@ -288,7 +288,7 @@
 # graal.nodes
 project@com.oracle.graal.nodes@subDir=graal
 project@com.oracle.graal.nodes@sourceDirs=src
-project@com.oracle.graal.nodes@dependencies=com.oracle.graal.api.code,com.oracle.graal.graph,com.oracle.graal.debug,com.oracle.graal.api.replacements
+project@com.oracle.graal.nodes@dependencies=com.oracle.graal.graph,com.oracle.graal.debug,com.oracle.graal.api.replacements,com.oracle.graal.api.code
 project@com.oracle.graal.nodes@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.nodes@javaCompliance=1.7
 project@com.oracle.graal.nodes@workingSets=Graal,Graph
--- a/mx/sanitycheck.py	Tue Sep 10 16:32:27 2013 -0700
+++ b/mx/sanitycheck.py	Tue Sep 10 16:33:28 2013 -0700
@@ -27,31 +27,31 @@
 import re, mx, commands, os, sys, StringIO, subprocess
 from os.path import isfile, join, exists
 
-gc='UseSerialGC'
+gc = 'UseSerialGC'
 
 dacapoSanityWarmup = {
-    'avrora':     [0, 0,  3,  6, 13],
-    'batik':      [0, 0,  5,  5, 20],
-    'eclipse':    [2, 4,  5, 10, 16],
+    'avrora':     [0, 0, 3, 6, 13],
+    'batik':      [0, 0, 5, 5, 20],
+    'eclipse':    [2, 4, 5, 10, 16],
     'fop':        [4, 8, 10, 20, 30],
-    'h2':         [0, 0,  5,  5,  8],
-    'jython':     [0, 0,  5, 10, 13],
-    'luindex':    [0, 0,  5, 10, 10],
-    'lusearch':   [0, 4,  5,  5,  8],
-    'pmd':        [0, 0,  5, 10, 13],
-    'sunflow':    [0, 2,  5, 10, 15],
-    'tomcat':     [0, 0,  5, 10, 15],
-    'tradebeans': [0, 0,  5, 10, 13],
-    'tradesoap':  [2, 4,  5, 10, 15],
-    'xalan':      [0, 0,  5, 10, 18],
+    'h2':         [0, 0, 5, 5, 8],
+    'jython':     [0, 0, 5, 10, 13],
+    'luindex':    [0, 0, 5, 10, 10],
+    'lusearch':   [0, 4, 5, 5, 8],
+    'pmd':        [0, 0, 5, 10, 13],
+    'sunflow':    [0, 2, 5, 10, 15],
+    'tomcat':     [0, 0, 5, 10, 15],
+    'tradebeans': [0, 0, 5, 10, 13],
+    'tradesoap':  [2, 4, 5, 10, 15],
+    'xalan':      [0, 0, 5, 10, 18],
 }
 
 dacapoScalaSanityWarmup = {
 # (tw) actors sometimes fails verification; hardly reproducible
-    'actors':     [0, 0, 0,  0,  0],
+    'actors':     [0, 0, 0, 0, 0],
 # (lstadler) apparat was disabled due to a deadlock which I think is the benchmarks fault.
-    'apparat':    [0, 0, 0,  0,  0],
-    'factorie':   [0, 0, 2,  5,  5],
+    'apparat':    [0, 0, 0, 0, 0],
+    'factorie':   [0, 0, 2, 5, 5],
     'kiama':      [0, 0, 3, 13, 15],
     'scalac':     [0, 0, 5, 15, 20],
     'scaladoc':   [0, 0, 5, 15, 15],
@@ -59,8 +59,8 @@
     'scalariform':[0, 0, 6, 15, 20],
     'scalatest':  [0, 0, 2, 10, 12],
     'scalaxb':    [0, 0, 5, 15, 25],
-#(gdub) specs sometimes returns a non-zero value event though there is no apparent failure
-    'specs':      [0, 0, 0,  0,  0],
+# (gdub) specs sometimes returns a non-zero value event though there is no apparent failure
+    'specs':      [0, 0, 0, 0, 0],
     'tmt':        [0, 0, 3, 10, 12]
 }
 
@@ -77,7 +77,8 @@
     'sunflow':    [           'fastdebug', 'debug'],
     'tomcat':     ['product', 'fastdebug', 'debug'],
     'tradebeans': ['product', 'fastdebug', 'debug'],
-    'tradesoap':  ['product'],
+    # tradesoap is too unreliable for the gate, often crashing with "java.net.BindException: Address already in use"
+    'tradesoap':  [                               ],
     'xalan':      ['product', 'fastdebug', 'debug'],
 }
 
@@ -137,60 +138,68 @@
     'xml.validation'
 ]
 
+def _noneAsEmptyList(a):
+    if a is None:
+        return []
+    return a
+
 class SanityCheckLevel:
     Fast, Gate, Normal, Extensive, Benchmark = range(5)
-    
-def getSPECjbb2005(benchArgs = []):
-    
+
+def getSPECjbb2005(benchArgs=None):
+    benchArgs = [] if benchArgs is None else benchArgs
+
     specjbb2005 = mx.get_env('SPECJBB2005')
     if specjbb2005 is None or not exists(join(specjbb2005, 'jbb.jar')):
         mx.abort('Please set the SPECJBB2005 environment variable to a SPECjbb2005 directory')
-    
+
     score = re.compile(r"^Valid run, Score is  (?P<score>[0-9]+)$", re.MULTILINE)
     error = re.compile(r"VALIDATION ERROR")
     success = re.compile(r"^Valid run, Score is  [0-9]+$", re.MULTILINE)
     matcher = ValuesMatcher(score, {'group' : 'SPECjbb2005', 'name' : 'score', 'score' : '<score>'})
     classpath = ['jbb.jar', 'check.jar']
-    return Test("SPECjbb2005", ['spec.jbb.JBBmain', '-propfile', 'SPECjbb.props'] + benchArgs, [success], [error], [matcher], vmOpts=['-Xms3g', '-XX:+'+gc, '-XX:-UseCompressedOops', '-cp', os.pathsep.join(classpath)], defaultCwd=specjbb2005)
+    return Test("SPECjbb2005", ['spec.jbb.JBBmain', '-propfile', 'SPECjbb.props'] + benchArgs, [success], [error], [matcher], vmOpts=['-Xms3g', '-XX:+' + gc, '-XX:-UseCompressedOops', '-cp', os.pathsep.join(classpath)], defaultCwd=specjbb2005)
 
-def getSPECjbb2013(benchArgs = []):
-    
+def getSPECjbb2013(benchArgs=None):
+
     specjbb2013 = mx.get_env('SPECJBB2013')
     if specjbb2013 is None or not exists(join(specjbb2013, 'specjbb2013.jar')):
         mx.abort('Please set the SPECJBB2013 environment variable to a SPECjbb2013 directory')
-    
+
     jops = re.compile(r"^RUN RESULT: hbIR \(max attempted\) = [0-9]+, hbIR \(settled\) = [0-9]+, max-jOPS = (?P<max>[0-9]+), critical-jOPS = (?P<critical>[0-9]+)$", re.MULTILINE)
-    #error?
+    # error?
     success = re.compile(r"org.spec.jbb.controller: Run finished", re.MULTILINE)
     matcherMax = ValuesMatcher(jops, {'group' : 'SPECjbb2013', 'name' : 'max', 'score' : '<max>'})
     matcherCritical = ValuesMatcher(jops, {'group' : 'SPECjbb2013', 'name' : 'critical', 'score' : '<critical>'})
-    return Test("SPECjbb2013", ['-jar', 'specjbb2013.jar', '-m', 'composite'] + benchArgs, [success], [], [matcherCritical, matcherMax], vmOpts=['-Xmx6g', '-Xms6g', '-Xmn3g', '-XX:+UseParallelOldGC', '-XX:-UseAdaptiveSizePolicy', '-XX:-UseBiasedLocking', '-XX:-UseCompressedOops'], defaultCwd=specjbb2013)
-    
-def getSPECjvm2008(benchArgs=[]):
-    
+    return Test("SPECjbb2013", ['-jar', 'specjbb2013.jar', '-m', 'composite'] +
+                _noneAsEmptyList(benchArgs), [success], [], [matcherCritical, matcherMax],
+                vmOpts=['-Xmx6g', '-Xms6g', '-Xmn3g', '-XX:+UseParallelOldGC', '-XX:-UseAdaptiveSizePolicy', '-XX:-UseBiasedLocking', '-XX:-UseCompressedOops'], defaultCwd=specjbb2013)
+
+def getSPECjvm2008(benchArgs=None):
+
     specjvm2008 = mx.get_env('SPECJVM2008')
     if specjvm2008 is None or not exists(join(specjvm2008, 'SPECjvm2008.jar')):
         mx.abort('Please set the SPECJVM2008 environment variable to a SPECjvm2008 directory')
-    
+
     score = re.compile(r"^(Score on|Noncompliant) (?P<benchmark>[a-zA-Z0-9\._]+)( result)?: (?P<score>[0-9]+((,|\.)[0-9]+)?)( SPECjvm2008 Base)? ops/m$", re.MULTILINE)
     error = re.compile(r"^Errors in benchmark: ", re.MULTILINE)
     # The ' ops/m' at the end of the success string is important : it's how you can tell valid and invalid runs apart
     success = re.compile(r"^(Noncompliant c|C)omposite result: [0-9]+((,|\.)[0-9]+)?( SPECjvm2008 (Base|Peak))? ops/m$", re.MULTILINE)
     matcher = ValuesMatcher(score, {'group' : 'SPECjvm2008', 'name' : '<benchmark>', 'score' : '<score>'})
-    
-    return Test("SPECjvm2008", ['-jar', 'SPECjvm2008.jar'] + benchArgs, [success], [error], [matcher], vmOpts=['-Xms3g', '-XX:+'+gc, '-XX:-UseCompressedOops'], defaultCwd=specjvm2008)
+
+    return Test("SPECjvm2008", ['-jar', 'SPECjvm2008.jar'] + _noneAsEmptyList(benchArgs), [success], [error], [matcher], vmOpts=['-Xms3g', '-XX:+' + gc, '-XX:-UseCompressedOops'], defaultCwd=specjvm2008)
 
-def getDacapos(level=SanityCheckLevel.Normal, gateBuildLevel=None, dacapoArgs=[]):
+def getDacapos(level=SanityCheckLevel.Normal, gateBuildLevel=None, dacapoArgs=None):
     checks = []
-    
+
     for (bench, ns) in dacapoSanityWarmup.items():
         if ns[level] > 0:
             if gateBuildLevel is None or gateBuildLevel in dacapoGateBuildLevels[bench]:
-                checks.append(getDacapo(bench, ['-n', str(ns[level])] + dacapoArgs))
-    
+                checks.append(getDacapo(bench, ['-n', str(ns[level])] + _noneAsEmptyList(dacapoArgs)))
+
     return checks
 
-def getDacapo(name, dacapoArgs=[]):
+def getDacapo(name, dacapoArgs=None):
     dacapo = mx.get_env('DACAPO_CP')
     if dacapo is None:
         l = mx.library('DACAPO', False)
@@ -198,31 +207,31 @@
             dacapo = l.get_path(True)
         else:
             mx.abort('DaCapo 9.12 jar file must be specified with DACAPO_CP environment variable or as DACAPO library')
-    
+
     if not isfile(dacapo) or not dacapo.endswith('.jar'):
         mx.abort('Specified DaCapo jar file does not exist or is not a jar file: ' + dacapo)
-    
+
     dacapoSuccess = re.compile(r"^===== DaCapo 9\.12 ([a-zA-Z0-9_]+) PASSED in ([0-9]+) msec =====$", re.MULTILINE)
     dacapoFail = re.compile(r"^===== DaCapo 9\.12 ([a-zA-Z0-9_]+) FAILED (warmup|) =====$", re.MULTILINE)
     dacapoTime = re.compile(r"===== DaCapo 9\.12 (?P<benchmark>[a-zA-Z0-9_]+) PASSED in (?P<time>[0-9]+) msec =====")
     dacapoTime1 = re.compile(r"===== DaCapo 9\.12 (?P<benchmark>[a-zA-Z0-9_]+) completed warmup 1 in (?P<time>[0-9]+) msec =====")
-    
+
     dacapoMatcher = ValuesMatcher(dacapoTime, {'group' : 'DaCapo', 'name' : '<benchmark>', 'score' : '<time>'})
     dacapoMatcher1 = ValuesMatcher(dacapoTime1, {'group' : 'DaCapo-1stRun', 'name' : '<benchmark>', 'score' : '<time>'})
-    
-    return Test("DaCapo-" + name, ['-jar', dacapo, name] + dacapoArgs, [dacapoSuccess], [dacapoFail], [dacapoMatcher, dacapoMatcher1], ['-Xms2g', '-XX:+'+gc, '-XX:-UseCompressedOops'])
+
+    return Test("DaCapo-" + name, ['-jar', dacapo, name] + _noneAsEmptyList(dacapoArgs), [dacapoSuccess], [dacapoFail], [dacapoMatcher, dacapoMatcher1], ['-Xms2g', '-XX:+' + gc, '-XX:-UseCompressedOops'])
 
-def getScalaDacapos(level=SanityCheckLevel.Normal, gateBuildLevel=None, dacapoArgs=[]):
+def getScalaDacapos(level=SanityCheckLevel.Normal, gateBuildLevel=None, dacapoArgs=None):
     checks = []
-    
+
     for (bench, ns) in dacapoScalaSanityWarmup.items():
         if ns[level] > 0:
             if gateBuildLevel is None or gateBuildLevel in dacapoScalaGateBuildLevels[bench]:
-                checks.append(getScalaDacapo(bench, ['-n', str(ns[level])] + dacapoArgs))
-    
+                checks.append(getScalaDacapo(bench, ['-n', str(ns[level])] + _noneAsEmptyList(dacapoArgs)))
+
     return checks
 
-def getScalaDacapo(name, dacapoArgs=[]):
+def getScalaDacapo(name, dacapoArgs=None):
     dacapo = mx.get_env('DACAPO_SCALA_CP')
     if dacapo is None:
         l = mx.library('DACAPO_SCALA', False)
@@ -230,23 +239,23 @@
             dacapo = l.get_path(True)
         else:
             mx.abort('Scala DaCapo 0.1.0 jar file must be specified with DACAPO_SCALA_CP environment variable or as DACAPO_SCALA library')
-    
+
     if not isfile(dacapo) or not dacapo.endswith('.jar'):
         mx.abort('Specified Scala DaCapo jar file does not exist or is not a jar file: ' + dacapo)
-    
+
     dacapoSuccess = re.compile(r"^===== DaCapo 0\.1\.0(-SNAPSHOT)? ([a-zA-Z0-9_]+) PASSED in ([0-9]+) msec =====$", re.MULTILINE)
     dacapoFail = re.compile(r"^===== DaCapo 0\.1\.0(-SNAPSHOT)? ([a-zA-Z0-9_]+) FAILED (warmup|) =====$", re.MULTILINE)
     dacapoTime = re.compile(r"===== DaCapo 0\.1\.0(-SNAPSHOT)? (?P<benchmark>[a-zA-Z0-9_]+) PASSED in (?P<time>[0-9]+) msec =====")
-    
+
     dacapoMatcher = ValuesMatcher(dacapoTime, {'group' : "Scala-DaCapo", 'name' : '<benchmark>', 'score' : '<time>'})
-    
-    return Test("Scala-DaCapo-" + name, ['-jar', dacapo, name] + dacapoArgs, [dacapoSuccess], [dacapoFail], [dacapoMatcher], ['-Xms2g', '-XX:+'+gc, '-XX:-UseCompressedOops'])
+
+    return Test("Scala-DaCapo-" + name, ['-jar', dacapo, name] + _noneAsEmptyList(dacapoArgs), [dacapoSuccess], [dacapoFail], [dacapoMatcher], ['-Xms2g', '-XX:+' + gc, '-XX:-UseCompressedOops'])
 
 def getBootstraps():
     time = re.compile(r"Bootstrapping Graal\.+ in (?P<time>[0-9]+) ms")
     scoreMatcher = ValuesMatcher(time, {'group' : 'Bootstrap', 'name' : 'BootstrapTime', 'score' : '<time>'})
     scoreMatcherBig = ValuesMatcher(time, {'group' : 'Bootstrap-bigHeap', 'name' : 'BootstrapTime', 'score' : '<time>'})
-    
+
     tests = []
     tests.append(Test("Bootstrap", ['-version'], successREs=[time], scoreMatchers=[scoreMatcher], ignoredVMs=['client', 'server'], benchmarkCompilationRate=False))
     tests.append(Test("Bootstrap-bigHeap", ['-version'], successREs=[time], scoreMatchers=[scoreMatcherBig], vmOpts=['-Xms2g'], ignoredVMs=['client', 'server'], benchmarkCompilationRate=False))
@@ -255,16 +264,16 @@
 class CTWMode:
     Full, NoInline, NoComplex = range(3)
 
-def getCTW(vm,mode):
+def getCTW(vm, mode):
     time = re.compile(r"CompileTheWorld : Done \([0-9]+ classes, [0-9]+ methods, (?P<time>[0-9]+) ms\)")
     scoreMatcher = ValuesMatcher(time, {'group' : 'CompileTheWorld', 'name' : 'CompileTime', 'score' : '<time>'})
-    
+
     jre = os.environ.get('JAVA_HOME')
     if exists(join(jre, 'jre')):
         jre = join(jre, 'jre')
     rtjar = join(jre, 'lib', 'rt.jar')
 
-    
+
     args = ['-XX:+CompileTheWorld', '-Xbootclasspath/p:' + rtjar]
     if commands.isGraalEnabled(vm):
         args += ['-XX:+BootstrapGraal', '-G:-Debug']
@@ -276,9 +285,9 @@
     if mode >= CTWMode.NoComplex:
         if commands.isGraalEnabled(vm):
             args += ['-G:-OptLoopTransform', '-G:-OptTailDuplication', '-G:-FullUnroll', '-G:-MemoryAwareScheduling', '-G:-NewMemoryAwareScheduling', '-G:-PartialEscapeAnalysis']
-        
+
     return Test("CompileTheWorld", args, successREs=[time], scoreMatchers=[scoreMatcher], benchmarkCompilationRate=False)
-    
+
 
 class Tee:
     def __init__(self):
@@ -291,24 +300,24 @@
 Encapsulates a single program that is a sanity test and/or a benchmark.
 """
 class Test:
-    def __init__(self, name, cmd, successREs=[], failureREs=[], scoreMatchers=[], vmOpts=[], defaultCwd=None, ignoredVMs=[], benchmarkCompilationRate=False):
+    def __init__(self, name, cmd, successREs=None, failureREs=None, scoreMatchers=None, vmOpts=None, defaultCwd=None, ignoredVMs=None, benchmarkCompilationRate=False):
 
         self.name = name
-        self.successREs = successREs
-        self.failureREs = failureREs + [re.compile(r"Exception occurred in scope: ")]
-        self.scoreMatchers = scoreMatchers
-        self.vmOpts = vmOpts
+        self.successREs = _noneAsEmptyList(successREs)
+        self.failureREs = _noneAsEmptyList(failureREs) + [re.compile(r"Exception occurred in scope: ")]
+        self.scoreMatchers = _noneAsEmptyList(scoreMatchers)
+        self.vmOpts = _noneAsEmptyList(vmOpts)
         self.cmd = cmd
         self.defaultCwd = defaultCwd
-        self.ignoredVMs = ignoredVMs
+        self.ignoredVMs = _noneAsEmptyList(ignoredVMs)
         self.benchmarkCompilationRate = benchmarkCompilationRate
         if benchmarkCompilationRate:
             self.vmOpts = self.vmOpts + ['-XX:+CITime']
-        
+
     def __str__(self):
         return self.name
-    
-    def test(self, vm, cwd=None, extraVmOpts=[], vmbuild=None):
+
+    def test(self, vm, cwd=None, extraVmOpts=None, vmbuild=None):
         """
         Run this program as a sanity test.
         """
@@ -319,27 +328,27 @@
         parser = OutputParser()
         jvmError = re.compile(r"(?P<jvmerror>([A-Z]:|/).*[/\\]hs_err_pid[0-9]+\.log)")
         parser.addMatcher(ValuesMatcher(jvmError, {'jvmError' : '<jvmerror>'}))
-        
+
         for successRE in self.successREs:
             parser.addMatcher(ValuesMatcher(successRE, {'passed' : '1'}))
         for failureRE in self.failureREs:
             parser.addMatcher(ValuesMatcher(failureRE, {'failed' : '1'}))
 
         tee = Tee()
-        retcode = commands.vm(self.vmOpts + extraVmOpts + self.cmd, vm, nonZeroIsFatal=False, out=tee.eat, err=subprocess.STDOUT, cwd=cwd, vmbuild=vmbuild)
+        retcode = commands.vm(self.vmOpts + _noneAsEmptyList(extraVmOpts) + self.cmd, vm, nonZeroIsFatal=False, out=tee.eat, err=subprocess.STDOUT, cwd=cwd, vmbuild=vmbuild)
         output = tee.output.getvalue()
         valueMaps = parser.parse(output)
 
         if len(valueMaps) == 0:
             return False
-        
+
         record = {}
         for valueMap in valueMaps:
             for key, value in valueMap.items():
                 if record.has_key(key) and record[key] != value:
                     mx.abort('Inconsistant values returned by test machers : ' + str(valueMaps))
                 record[key] = value
-        
+
         jvmErrorFile = record.get('jvmError')
         if jvmErrorFile:
             mx.log('/!\\JVM Error : dumping error log...')
@@ -347,13 +356,13 @@
                 mx.log(fp.read())
             os.unlink(jvmErrorFile)
             return False
-        
+
         if record.get('failed') == '1':
             return False
-        
+
         return retcode == 0 and record.get('passed') == '1'
-    
-    def bench(self, vm, cwd=None, extraVmOpts=[], vmbuild=None):
+
+    def bench(self, vm, cwd=None, extraVmOpts=None, vmbuild=None):
         """
         Run this program as a benchmark.
         """
@@ -362,7 +371,7 @@
         if cwd is None:
             cwd = self.defaultCwd
         parser = OutputParser()
-        
+
         for successRE in self.successREs:
             parser.addMatcher(ValuesMatcher(successRE, {'passed' : '1'}))
         for failureRE in self.failureREs:
@@ -379,10 +388,10 @@
             else:
                 ibps = re.compile(r"(?P<compiler>[\w]+) compilation speed: +(?P<rate>[0-9]+) bytes/s {standard")
                 parser.addMatcher(ValuesMatcher(ibps, {'group' : 'InlinedBytecodesPerSecond', 'name' : '<compiler>:' + self.name, 'score' : '<rate>'}))
-            
+
         startDelim = 'START: ' + self.name
         endDelim = 'END: ' + self.name
-        
+
         outputfile = os.environ.get('BENCH_OUTPUT', None)
         if outputfile:
             # Used only to debug output parsing
@@ -399,7 +408,7 @@
         else:
             tee = Tee()
             mx.log(startDelim)
-            if commands.vm(self.vmOpts + extraVmOpts + self.cmd, vm, nonZeroIsFatal=False, out=tee.eat, err=subprocess.STDOUT, cwd=cwd, vmbuild=vmbuild) != 0:
+            if commands.vm(self.vmOpts + _noneAsEmptyList(extraVmOpts) + self.cmd, vm, nonZeroIsFatal=False, out=tee.eat, err=subprocess.STDOUT, cwd=cwd, vmbuild=vmbuild) != 0:
                 mx.abort("Benchmark failed (non-zero retcode)")
             mx.log(endDelim)
             output = tee.output.getvalue()
@@ -419,8 +428,8 @@
                 score = valueMap.get('score')
                 if name and score:
                     group[name] = score
-        
+
         if not passed:
             mx.abort("Benchmark failed (not passed)")
-        
+
         return groups
--- a/mxtool/mx.py	Tue Sep 10 16:32:27 2013 -0700
+++ b/mxtool/mx.py	Tue Sep 10 16:33:28 2013 -0700
@@ -125,7 +125,7 @@
     javaCompliance
         The minimum JDK version (format: x.y) to which the project's
         sources comply (required for non-native projects).
-    
+
     workingSets
         A comma separated list of working set names. The project belongs
         to the given working sets, for which the eclipseinit command
@@ -146,8 +146,6 @@
 from argparse import ArgumentParser, REMAINDER
 from os.path import join, basename, dirname, exists, getmtime, isabs, expandvars, isdir, isfile
 
-DEFAULT_JAVA_ARGS = '-ea -Xss2m -Xmx1g'
-
 _projects = dict()
 _libs = dict()
 _dists = dict()
@@ -169,17 +167,17 @@
             self.path = join(suite.dir, self.path)
         self.deps = deps
         self.update_listeners = set()
-        
+
     def __str__(self):
         return self.name
-    
+
     def add_update_listener(self, listener):
         self.update_listeners.add(listener)
-        
+
     def notify_updated(self):
         for l in self.update_listeners:
             l(self)
-    
+
 """
 A dependency is a library or project specified in a suite.
 """
@@ -202,7 +200,7 @@
 
     def isLibrary(self):
         return isinstance(self, Library)
-    
+
     def isProject(self):
         return isinstance(self, Project)
 
@@ -216,7 +214,7 @@
         self.native = False
         self.workingSets = workingSets
         self.dir = d
-        
+
         # Create directories for projects that don't yet exist
         if not exists(d):
             os.mkdir(d)
@@ -244,7 +242,7 @@
         return deps
 
     def _compute_max_dep_distances(self, name, distances, dist):
-        currentDist = distances.get(name);
+        currentDist = distances.get(name)
         if currentDist is None or currentDist < dist:
             distances[name] = dist
             p = project(name, False)
@@ -260,14 +258,14 @@
         distances = dict()
         result = set()
         self._compute_max_dep_distances(self.name, distances, 0)
-        for n,d in distances.iteritems():
+        for n, d in distances.iteritems():
             assert d > 0 or n == self.name
             if d == 1:
                 result.add(n)
 
         if len(result) == len(self.deps) and frozenset(self.deps) == result:
             return self.deps
-        return result;
+        return result
 
     def max_depth(self):
         """
@@ -275,7 +273,7 @@
         """
         distances = dict()
         self._compute_max_dep_distances(self.name, distances, 0)
-        return max(distances.values())        
+        return max(distances.values())
 
     def source_dirs(self):
         """
@@ -337,23 +335,23 @@
                                     matchFound = True
                                 if pkg and matchFound:
                                     break
-                                        
+
                         if matchFound:
-                            basename = name[:-len('.java')]
+                            simpleClassName = name[:-len('.java')]
                             assert pkg is not None
                             if pkgRoot is None or pkg.startswith(pkgRoot):
                                 pkgOutputDir = join(outputDir, pkg.replace('.', os.path.sep))
                                 if exists(pkgOutputDir):
                                     for e in os.listdir(pkgOutputDir):
                                         if includeInnerClasses:
-                                            if e.endswith('.class') and (e.startswith(basename) or e.startswith(basename + '$')):
+                                            if e.endswith('.class') and (e.startswith(simpleClassName) or e.startswith(simpleClassName + '$')):
                                                 className = pkg + '.' + e[:-len('.class')]
                                                 result[className] = source
-                                        elif e == basename + '.class':
-                                            className = pkg + '.' + basename
+                                        elif e == simpleClassName + '.class':
+                                            className = pkg + '.' + simpleClassName
                                             result[className] = source
         return result
-    
+
     def _init_packages_and_imports(self):
         if not hasattr(self, '_defined_java_packages'):
             packages = set()
@@ -367,21 +365,21 @@
                 for root, _, files in os.walk(sourceDir):
                     javaSources = [name for name in files if name.endswith('.java')]
                     if len(javaSources) != 0:
-                        pkg = root[len(sourceDir) + 1:].replace(os.sep,'.')
+                        pkg = root[len(sourceDir) + 1:].replace(os.sep, '.')
                         if not pkg in depPackages:
                             packages.add(pkg)
                         else:
                             # A project extends a package already defined by one of it dependencies
                             extendedPackages.add(pkg)
                             imports.add(pkg)
-                        
+
                         for n in javaSources:
                             with open(join(root, n)) as fp:
                                 content = fp.read()
                                 imports.update(importRe.findall(content))
             self._defined_java_packages = frozenset(packages)
             self._extended_java_packages = frozenset(extendedPackages)
-            
+
             importedPackages = set()
             for imp in imports:
                 name = imp
@@ -394,12 +392,12 @@
                 if name is not None:
                     importedPackages.add(name)
             self._imported_java_packages = frozenset(importedPackages)
-    
+
     def defined_java_packages(self):
         """Get the immutable set of Java packages defined by the Java sources of this project"""
         self._init_packages_and_imports()
         return self._defined_java_packages
-    
+
     def extended_java_packages(self):
         """Get the immutable set of Java packages extended by the Java sources of this project"""
         self._init_packages_and_imports()
@@ -417,7 +415,7 @@
             if hasattr(self, '_declaredAnnotationProcessors'):
                 ap = set(self._declaredAnnotationProcessors)
 
-            # find dependencies that auto-inject themselves as annotation processors to all dependents                
+            # find dependencies that auto-inject themselves as annotation processors to all dependents
             allDeps = self.all_deps([], includeLibs=False, includeSelf=False, includeAnnotationProcessors=False)
             for p in allDeps:
                 if hasattr(p, 'annotationProcessorForDependents') and p.annotationProcessorForDependents.lower() == 'true':
@@ -442,7 +440,7 @@
         if not isabs(path):
             path = join(self.suite.dir, path)
         if resolve and self.mustExist and not exists(path):
-            assert not len(self.urls) == 0, 'cannot find required library ' + self.name + ' ' + path;
+            assert not len(self.urls) == 0, 'cannot find required library ' + self.name + ' ' + path
             print('Downloading ' + self.name + ' from ' + str(self.urls))
             download(path, self.urls)
         return path
@@ -462,7 +460,7 @@
         path = self.get_path(resolve)
         if exists(path) or not resolve:
             cp.append(path)
-            
+
     def all_deps(self, deps, includeLibs, includeSelf=True, includeAnnotationProcessors=False):
         if not includeLibs or not includeSelf:
             return deps
@@ -482,11 +480,11 @@
         self._load_env(mxDir)
         self._load_commands(mxDir)
         self._load_includes(mxDir)
-        self.name = d # re-initialized in _load_projects
+        self.name = d  # re-initialized in _load_projects
 
     def __str__(self):
         return self.name
-    
+
     def _load_projects(self, mxDir):
         libsMap = dict()
         projsMap = dict()
@@ -536,7 +534,7 @@
             srcDirs = pop_list(attrs, 'sourceDirs')
             deps = pop_list(attrs, 'dependencies')
             ap = pop_list(attrs, 'annotationProcessors')
-            #deps += ap
+            # deps += ap
             javaCompliance = attrs.pop('javaCompliance', None)
             subDir = attrs.pop('subDir', None)
             if subDir is None:
@@ -570,17 +568,17 @@
             d = Distribution(self, name, path, deps)
             d.__dict__.update(attrs)
             self.dists.append(d)
-            
+
         if self.name is None:
             abort('Missing "suite=<name>" in ' + projectsFile)
 
     def _load_commands(self, mxDir):
-        commands = join(mxDir, 'commands.py')
-        if exists(commands):
+        commandsPath = join(mxDir, 'commands.py')
+        if exists(commandsPath):
             # temporarily extend the Python path
             sys.path.insert(0, mxDir)
             mod = __import__('commands')
-            
+
             self.commands = sys.modules.pop('commands')
             sys.modules[join(mxDir, 'commands')] = self.commands
 
@@ -588,7 +586,7 @@
             del sys.path[0]
 
             if not hasattr(mod, 'mx_init'):
-                abort(commands + ' must define an mx_init(env) function')
+                abort(commandsPath + ' must define an mx_init(env) function')
             if hasattr(mod, 'mx_post_parse_cmd_line'):
                 self.mx_post_parse_cmd_line = mod.mx_post_parse_cmd_line
 
@@ -632,7 +630,7 @@
                 abort('cannot redefine library  ' + l.name)
             _libs[l.name] = l
         for d in self.dists:
-            existing = _dists.get(l.name)
+            existing = _dists.get(d.name)
             if existing is not None:
                 abort('cannot redefine distribution  ' + d.name)
             _dists[d.name] = d
@@ -641,7 +639,7 @@
 
 class XMLElement(xml.dom.minidom.Element):
     def writexml(self, writer, indent="", addindent="", newl=""):
-        writer.write(indent+"<" + self.tagName)
+        writer.write(indent + "<" + self.tagName)
 
         attrs = self._get_attributes()
         a_names = attrs.keys()
@@ -657,14 +655,14 @@
                 # text is printed without any indentation or new line padding
                 writer.write(">")
                 self.childNodes[0].writexml(writer)
-                writer.write("</%s>%s" % (self.tagName,newl))
+                writer.write("</%s>%s" % (self.tagName, newl))
             else:
-                writer.write(">%s"%(newl))
+                writer.write(">%s" % (newl))
                 for node in self.childNodes:
-                    node.writexml(writer,indent+addindent,addindent,newl)
-                writer.write("%s</%s>%s" % (indent,self.tagName,newl))
+                    node.writexml(writer, indent + addindent, addindent, newl)
+                writer.write("%s</%s>%s" % (indent, self.tagName, newl))
         else:
-            writer.write("/>%s"%(newl))
+            writer.write("/>%s" % (newl))
 
 class XMLDoc(xml.dom.minidom.Document):
 
@@ -682,7 +680,9 @@
     def comment(self, txt):
         self.current.appendChild(self.createComment(txt))
 
-    def open(self, tag, attributes={}, data=None):
+    def open(self, tag, attributes=None, data=None):
+        if attributes is None:
+            attributes = {}
         element = self.createElement(tag)
         for key, value in attributes.items():
             element.setAttribute(key, value)
@@ -698,7 +698,9 @@
         self.current = self.current.parentNode
         return self
 
-    def element(self, tag, attributes={}, data=None):
+    def element(self, tag, attributes=None, data=None):
+        if attributes is None:
+            attributes = {}
         return self.open(tag, attributes, data).close(tag)
 
     def xml(self, indent='', newl='', escape=False, standalone=None):
@@ -888,7 +890,7 @@
 def _handle_missing_java_home():
     if not sys.stdout.isatty():
         abort('Could not find bootstrap JDK. Use --java-home option or ensure JAVA_HOME environment variable is set.')
- 
+
     candidateJdks = []
     if get_os() == 'darwin':
         base = '/Library/Java/JavaVirtualMachines'
@@ -908,7 +910,7 @@
         javaHome = select_items(candidateJdks + ['<other>'], allowMultiple=False)
         if javaHome == '<other>':
             javaHome = None
-            
+
     while javaHome is None:
         javaHome = raw_input('Enter path of bootstrap JDK: ')
         rtJarPath = join(javaHome, 'jre', 'lib', 'rt.jar')
@@ -917,13 +919,12 @@
             javaHome = None
         else:
             break
-    
+
     envPath = join(_mainSuite.dir, 'mx', 'env')
-    answer = raw_input('Persist this setting by adding "JAVA_HOME=' + javaHome + '" to ' + envPath + '? [Yn]: ')
-    if not answer.lower().startswith('n'):
+    if ask_yes_no('Persist this setting by adding "JAVA_HOME=' + javaHome + '" to ' + envPath, 'y'):
         with open(envPath, 'a') as fp:
             print >> fp, 'JAVA_HOME=' + javaHome
-            
+
     return javaHome
 
 class ArgParser(ArgumentParser):
@@ -943,7 +944,7 @@
         self.add_argument('-d', action='store_const', const=8000, dest='java_dbg_port', help='alias for "-dbg 8000"')
         self.add_argument('--cp-pfx', dest='cp_prefix', help='class path prefix', metavar='<arg>')
         self.add_argument('--cp-sfx', dest='cp_suffix', help='class path suffix', metavar='<arg>')
-        self.add_argument('--J', dest='java_args', help='Java VM arguments (e.g. --J @-dsa)', metavar='@<args>', default=DEFAULT_JAVA_ARGS)
+        self.add_argument('--J', dest='java_args', help='Java VM arguments (e.g. --J @-dsa)', metavar='@<args>', default='-ea -Xss2m -Xmx1g')
         self.add_argument('--Jp', action='append', dest='java_args_pfx', help='prefix Java VM arguments (e.g. --Jp @-dsa)', metavar='@<args>', default=[])
         self.add_argument('--Ja', action='append', dest='java_args_sfx', help='suffix Java VM arguments (e.g. --Ja @-dsa)', metavar='@<args>', default=[])
         self.add_argument('--user-home', help='users home directory', metavar='<path>', default=os.path.expanduser('~'))
@@ -988,8 +989,8 @@
 
 def _format_commands():
     msg = '\navailable commands:\n\n'
-    for cmd in sorted(commands.iterkeys()):
-        c, _ = commands[cmd][:2]
+    for cmd in sorted(_commands.iterkeys()):
+        c, _ = _commands[cmd][:2]
         doc = c.__doc__
         if doc is None:
             doc = ''
@@ -1076,7 +1077,7 @@
 
     if env is None:
         env = os.environ
-        
+
     if _opts.verbose:
         if _opts.very_verbose:
             log('Environment variables:')
@@ -1109,17 +1110,17 @@
                 for line in iter(stream.readline, ''):
                     f(line)
                 stream.close()
-            stdout=out if not callable(out) else subprocess.PIPE
-            stderr=err if not callable(err) else subprocess.PIPE
+            stdout = out if not callable(out) else subprocess.PIPE
+            stderr = err if not callable(err) else subprocess.PIPE
             p = subprocess.Popen(args, cwd=cwd, stdout=stdout, stderr=stderr, preexec_fn=preexec_fn, creationflags=creationflags, env=env)
             _currentSubprocess = (p, args)
             if callable(out):
                 t = Thread(target=redirect, args=(p.stdout, out))
-                t.daemon = True # thread dies with the program
+                t.daemon = True  # thread dies with the program
                 t.start()
             if callable(err):
                 t = Thread(target=redirect, args=(p.stderr, err))
-                t.daemon = True # thread dies with the program
+                t.daemon = True  # thread dies with the program
                 t.start()
             if timeout is None or timeout == 0:
                 retcode = waitOn(p)
@@ -1142,7 +1143,7 @@
             if _opts.very_verbose:
                 raise subprocess.CalledProcessError(retcode, ' '.join(args))
             else:
-                log('[exit code: ' + str(retcode)+ ']')
+                log('[exit code: ' + str(retcode) + ']')
         abort(retcode)
 
     return retcode
@@ -1159,7 +1160,7 @@
     """
     Adds the platform specific library prefix to a name
     """
-    os = get_os();
+    os = get_os()
     if os == 'linux' or os == 'solaris' or os == 'darwin':
         return 'lib' + name
     return name
@@ -1168,7 +1169,7 @@
     """
     Adds the platform specific library suffix to a name
     """
-    os = get_os();
+    os = get_os()
     if os == 'windows':
         return name + '.dll'
     if os == 'linux' or os == 'solaris':
@@ -1182,7 +1183,7 @@
 """
 class JavaCompliance:
     def __init__(self, ver):
-        m = re.match('1\.(\d+).*', ver)
+        m = re.match(r'1\.(\d+).*', ver)
         assert m is not None, 'not a recognized version string: ' + ver
         self.value = int(m.group(1))
 
@@ -1194,22 +1195,22 @@
             other = JavaCompliance(other)
 
         return cmp(self.value, other.value)
-    
+
 """
 A Java version as defined in JSR-56
 """
 class JavaVersion:
     def __init__(self, versionString):
-        validChar = '[\x21-\x25\x27-\x29\x2c\x2f-\x5e\x60-\x7f]'
-        separator = '[.\-_]'
+        validChar = r'[\x21-\x25\x27-\x29\x2c\x2f-\x5e\x60-\x7f]'
+        separator = r'[.\-_]'
         m = re.match(validChar + '+(' + separator + validChar + '+)*', versionString)
         assert m is not None, 'not a recognized version string: ' + versionString
-        self.versionString = versionString;
+        self.versionString = versionString
         self.parts = [int(f) if f.isdigit() else f for f in re.split(separator, versionString)]
-        
+
     def __str__(self):
         return self.versionString
-    
+
     def __cmp__(self, other):
         return cmp(self.parts, other.parts)
 
@@ -1220,8 +1221,8 @@
     def __init__(self, opts):
         self.jdk = opts.java_home
         self.debug_port = opts.java_dbg_port
-        self.jar   = exe_suffix(join(self.jdk, 'bin', 'jar'))
-        self.java  = exe_suffix(join(self.jdk, 'bin', 'java'))
+        self.jar = exe_suffix(join(self.jdk, 'bin', 'jar'))
+        self.java = exe_suffix(join(self.jdk, 'bin', 'java'))
         self.javac = exe_suffix(join(self.jdk, 'bin', 'javac'))
         self.javap = exe_suffix(join(self.jdk, 'bin', 'javap'))
         self.javadoc = exe_suffix(join(self.jdk, 'bin', 'javadoc'))
@@ -1299,7 +1300,7 @@
 def logv(msg=None):
     if _opts.verbose:
         log(msg)
-    
+
 def log(msg=None):
     """
     Write a message to the console.
@@ -1333,16 +1334,16 @@
         try:
             output = subprocess.check_output([a, '--version'])
             if 'GNU' in output:
-                return a;
+                return a
         except:
             pass
     abort('Could not find a GNU make executable on the current path.')
 
 def expandvars_in_property(value):
-        result = expandvars(value)
-        if '$' in result or '%' in result:
-            abort('Property contains an undefined environment variable: ' + value)
-        return result
+    result = expandvars(value)
+    if '$' in result or '%' in result:
+        abort('Property contains an undefined environment variable: ' + value)
+    return result
 
 
 def abort(codeOrMessage):
@@ -1353,8 +1354,8 @@
     the object's value is printed and the exit status is one.
     """
 
-    #import traceback
-    #traceback.print_stack()
+    # import traceback
+    # traceback.print_stack()
     currentSubprocess = _currentSubprocess
     if currentSubprocess is not None:
         p, _ = currentSubprocess
@@ -1362,7 +1363,7 @@
             p.kill()
         else:
             _kill_process_group(p.pid)
-    
+
     raise SystemExit(codeOrMessage)
 
 def download(path, urls, verbose=False):
@@ -1452,9 +1453,9 @@
             f.write(content)
 
         log(('modified ' if existed else 'created ') + path)
-        return True;
+        return True
     except IOError as e:
-        abort('Error while writing to ' + path + ': ' + str(e));
+        abort('Error while writing to ' + path + ': ' + str(e))
 
 # Builtin commands
 
@@ -1488,11 +1489,11 @@
         parser.add_argument('remainder', nargs=REMAINDER, metavar='...')
 
     args = parser.parse_args(args)
-    
+
     jdtJar = None
     if args.jdt is not None:
         if args.jdt.endswith('.jar'):
-            jdtJar=args.jdt
+            jdtJar = args.jdt
             if not exists(jdtJar) and os.path.abspath(jdtJar) == os.path.abspath(defaultEcjPath):
                 # Silently ignore JDT if default location is used but not ecj.jar exists there
                 jdtJar = None
@@ -1507,7 +1508,7 @@
         sortedProjects = [project(name) for name in args.only.split(',')]
     else:
         sortedProjects = sorted_deps(projects, includeAnnotationProcessors=True)
-    
+
     for p in sortedProjects:
         if p.native:
             if args.native:
@@ -1522,7 +1523,7 @@
         else:
             if not args.java:
                 continue
-            if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
+            if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
                 continue
 
         # skip building this Java project if its Java compliance level is "higher" than the configured JDK
@@ -1621,11 +1622,11 @@
         ap = p.annotation_processors()
         if len(ap) > 0:
             processorPath = classpath(ap, resolve=True)
-            genDir = p.source_gen_dir();
+            genDir = p.source_gen_dir()
             if exists(genDir):
                 shutil.rmtree(genDir)
             os.mkdir(genDir)
-            processorArgs += ['-processorpath', join(processorPath), '-s', genDir] 
+            processorArgs += ['-processorpath', join(processorPath), '-s', genDir]
         else:
             processorArgs += ['-proc:none']
 
@@ -1634,20 +1635,20 @@
             compliance = str(p.javaCompliance) if p.javaCompliance is not None else args.compliance
             if jdtJar is None:
                 log('Compiling Java sources for {0} with javac...'.format(p.name))
-                
-                
+
+
                 javacCmd = [java().javac, '-g', '-J-Xmx1g', '-source', compliance, '-classpath', cp, '-d', outputDir]
                 if java().debug_port is not None:
                     javacCmd += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(java().debug_port)]
                 javacCmd += processorArgs
                 javacCmd += ['@' + argfile.name]
-                
+
                 if not args.warnAPI:
                     javacCmd.append('-XDignore.symbol.file')
                 run(javacCmd)
             else:
                 log('Compiling Java sources for {0} with JDT...'.format(p.name))
-                                
+
                 jdtArgs = [java().java, '-Xmx1g']
                 if java().debug_port is not None:
                     jdtArgs += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(java().debug_port)]
@@ -1657,8 +1658,8 @@
                          '-cp', cp, '-g', '-enableJavadoc',
                          '-d', outputDir]
                 jdtArgs += processorArgs
-                         
-                         
+
+
                 jdtProperties = join(p.dir, '.settings', 'org.eclipse.jdt.core.prefs')
                 rootJdtProperties = join(p.suite.dir, 'mx', 'eclipse-settings', 'org.eclipse.jdt.core.prefs')
                 if not exists(jdtProperties) or os.path.getmtime(jdtProperties) < os.path.getmtime(rootJdtProperties):
@@ -1679,12 +1680,12 @@
                     else:
                         jdtArgs += ['-properties', jdtProperties]
                 jdtArgs.append('@' + argfile.name)
-                
+
                 run(jdtArgs)
         finally:
             for n in toBeDeleted:
                 os.remove(n)
-                
+
     for dist in _dists.values():
         archive(['@' + dist.name])
 
@@ -1701,17 +1702,17 @@
     parser.add_argument('-e', '--eclipse-exe', help='location of the Eclipse executable')
     parser.add_argument('-C', '--no-backup', action='store_false', dest='backup', help='do not save backup of modified files')
     parser.add_argument('--projects', action='store', help='comma separated projects to process (omit to process all projects)')
-    
+
     args = parser.parse_args(args)
     if args.eclipse_exe is None:
         args.eclipse_exe = os.environ.get('ECLIPSE_EXE')
     if args.eclipse_exe is None:
         abort('Could not find Eclipse executable. Use -e option or ensure ECLIPSE_EXE environment variable is set.')
-        
+
     # Maybe an Eclipse installation dir was specified - look for the executable in it
     if join(args.eclipse_exe, exe_suffix('eclipse')):
         args.eclipse_exe = join(args.eclipse_exe, exe_suffix('eclipse'))
-        
+
     if not os.path.isfile(args.eclipse_exe) or not os.access(args.eclipse_exe, os.X_OK):
         abort('Not an executable file: ' + args.eclipse_exe)
 
@@ -1726,7 +1727,7 @@
         def __init__(self, settingsFile):
             self.path = settingsFile
             self.javafiles = list()
-            
+
         def settings(self):
             with open(self.path) as fp:
                 return fp.read()
@@ -1745,14 +1746,14 @@
                     self.content = content
                     return True
             os.utime(self.path, self.times)
-            
+
     modified = list()
-    batches = dict() # all sources with the same formatting settings are formatted together
+    batches = dict()  # all sources with the same formatting settings are formatted together
     for p in projects:
         if p.native:
             continue
         sourceDirs = p.source_dirs()
-        
+
         batch = Batch(join(p.dir, '.settings', 'org.eclipse.jdt.core.prefs'))
 
         if not exists(batch.path):
@@ -1777,7 +1778,7 @@
         for fi in batch.javafiles:
             if fi.update():
                 modified.append(fi)
-                
+
     log('{0} files were modified'.format(len(modified)))
     if len(modified) != 0:
         if args.backup:
@@ -1793,25 +1794,25 @@
     return 0
 
 def processorjars():
-    
+
     projs = set()
     for p in sorted_deps():
         if _isAnnotationProcessorDependency(p):
             projs.add(p)
-            
+
     if len(projs) < 0:
         return
-    
+
     pnames = [p.name for p in projs]
     build(['--projects', ",".join(pnames)])
     archive(pnames)
 
 def archive(args):
     """create jar files for projects and distributions"""
-    parser = ArgumentParser(prog='mx archive');
+    parser = ArgumentParser(prog='mx archive')
     parser.add_argument('names', nargs=REMAINDER, metavar='[<project>|@<distribution>]...')
     args = parser.parse_args(args)
-    
+
     for name in args.names:
         if name.startswith('@'):
             dname = name[1:]
@@ -1822,7 +1823,7 @@
             def overwriteCheck(zf, arcname, source):
                 if arcname in zf.namelist():
                     log('warning: ' + d.path + ': overwriting ' + arcname + ' [source: ' + source + ']')
-                
+
             try:
                 zf = zipfile.ZipFile(tmp, 'w')
                 for dep in sorted_deps(d.deps, includeLibs=True):
@@ -1847,7 +1848,7 @@
                         if java().javaCompliance < p.javaCompliance:
                             log('Excluding {0} from {2} (Java compliance level {1} required)'.format(p.name, p.javaCompliance, d.path))
                             continue
-    
+
                         logv('[' + d.path + ': adding project ' + p.name + ']')
                         outputDir = p.output_dir()
                         for root, _, files in os.walk(outputDir):
@@ -1877,7 +1878,7 @@
                 shutil.rmtree(services)
                 # Atomic on Unix
                 shutil.move(tmp, d.path)
-                #print time.time(), 'move:', tmp, '->', d.path
+                # print time.time(), 'move:', tmp, '->', d.path
                 d.notify_updated()
             finally:
                 if exists(tmp):
@@ -1925,11 +1926,11 @@
                     out.write(line + '\n')
                 else:
                     p = project(m.group(1))
-                    
+
                     for pkg in p.defined_java_packages():
                         if not pkg.startswith(p.name):
                             abort('package in {0} does not have prefix matching project name: {1}'.format(p, pkg))
-                    
+
                     ignoredDeps = set([name for name in p.deps if project(name, False) is not None])
                     for pkg in p.imported_java_packages():
                         for name in p.deps:
@@ -1942,7 +1943,7 @@
                                 if pkg in dep.extended_java_packages():
                                     ignoredDeps.discard(name)
                     if len(ignoredDeps) != 0:
-                        candidates = set();
+                        candidates = set()
                         # Compute dependencies based on projects required by p
                         for d in sorted_deps():
                             if not d.defined_java_packages().isdisjoint(p.imported_java_packages()):
@@ -1951,16 +1952,16 @@
                         for c in list(candidates):
                             candidates.difference_update(c.all_deps([], False, False))
                         candidates = [d.name for d in candidates]
-                        
+
                         abort('{0}:{1}: {2} does not use any packages defined in these projects: {3}\nComputed project dependencies: {4}'.format(
                             projectsFile, lineNo, p, ', '.join(ignoredDeps), ','.join(candidates)))
-                    
+
                     out.write('project@' + m.group(1) + '@dependencies=' + ','.join(p.canonical_deps()) + '\n')
                 lineNo = lineNo + 1
             content = out.getvalue()
         if update_file(projectsFile, content):
             changedFiles += 1
-    return changedFiles;
+    return changedFiles
 
 def checkstyle(args):
     """run Checkstyle on the Java sources
@@ -1972,7 +1973,7 @@
 
     parser.add_argument('-f', action='store_true', dest='force', help='force checking (disables timestamp checking)')
     args = parser.parse_args(args)
-    
+
     totalErrors = 0
     for p in sorted_deps():
         if p.native:
@@ -1982,7 +1983,7 @@
 
         if not exists(dotCheckstyle):
             continue
-        
+
         # skip checking this Java project if its Java compliance level is "higher" than the configured JDK
         if java().javaCompliance < p.javaCompliance:
             log('Excluding {0} from checking (Java compliance level {1} required)'.format(p.name, p.javaCompliance))
@@ -2075,13 +2076,12 @@
                     finally:
                         if exists(auditfileName):
                             errors = []
-                            source = None
+                            source = [None]
                             def start_element(name, attrs):
                                 if name == 'file':
-                                    global source
-                                    source = attrs['name']
+                                    source[0] = attrs['name']
                                 elif name == 'error':
-                                    errors.append('{}:{}: {}'.format(source, attrs['line'], attrs['message']))
+                                    errors.append('{}:{}: {}'.format(source[0], attrs['line'], attrs['message']))
 
                             p = xml.parsers.expat.ParserCreate()
                             p.StartElementHandler = start_element
@@ -2109,7 +2109,7 @@
 
     suppliedParser = parser is not None
 
-    parser = parser if suppliedParser else ArgumentParser(prog='mx build');
+    parser = parser if suppliedParser else ArgumentParser(prog='mx build')
     parser.add_argument('--no-native', action='store_false', dest='native', help='do not clean native projects')
     parser.add_argument('--no-java', action='store_false', dest='java', help='do not clean Java projects')
 
@@ -2121,13 +2121,13 @@
                 run([gmake_cmd(), '-C', p.dir, 'clean'])
         else:
             if args.java:
-                genDir = p.source_gen_dir();
+                genDir = p.source_gen_dir()
                 if genDir != '' and exists(genDir):
                     log('Clearing {0}...'.format(genDir))
                     for f in os.listdir(genDir):
                         shutil.rmtree(join(genDir, f))
-                    
-                    
+
+
                 outputDir = p.output_dir()
                 if outputDir != '' and exists(outputDir):
                     log('Removing {0}...'.format(outputDir))
@@ -2151,8 +2151,8 @@
         return
 
     name = args[0]
-    if not commands.has_key(name):
-        hits = [c for c in commands.iterkeys() if c.startswith(name)]
+    if not _commands.has_key(name):
+        hits = [c for c in _commands.iterkeys() if c.startswith(name)]
         if len(hits) == 1:
             name = hits[0]
         elif len(hits) == 0:
@@ -2160,7 +2160,7 @@
         else:
             abort('mx: command \'{0}\' is ambiguous\n    {1}'.format(name, ' '.join(hits)))
 
-    value = commands[name]
+    value = _commands[name]
     (func, usage) = value[:2]
     doc = func.__doc__
     if len(value) > 2:
@@ -2207,10 +2207,12 @@
     slm.close('sourceLookupDirector')
     return slm
 
-def make_eclipse_attach(hostname, port, name=None, deps=[]):
+def make_eclipse_attach(hostname, port, name=None, deps=None):
     """
     Creates an Eclipse launch configuration file for attaching to a Java process.
     """
+    if deps is None:
+        deps = []
     slm = _source_locator_memento(deps)
     launch = XMLDoc()
     launch.open('launchConfiguration', {'type' : 'org.eclipse.jdt.launching.remoteJavaApplication'})
@@ -2233,10 +2235,12 @@
         os.makedirs(eclipseLaunches)
     return update_file(join(eclipseLaunches, name + '.launch'), launch)
 
-def make_eclipse_launch(javaArgs, jre, name=None, deps=[]):
+def make_eclipse_launch(javaArgs, jre, name=None, deps=None):
     """
     Creates an Eclipse launch configuration file for running/debugging a Java command.
     """
+    if deps is None:
+        deps = []
     mainClass = None
     vmArgs = []
     appArgs = []
@@ -2303,7 +2307,7 @@
 
     if suite is None:
         suite = _mainSuite
-        
+
     if buildProcessorJars:
         processorjars()
 
@@ -2330,7 +2334,7 @@
             out.element('classpathentry', {'kind' : 'src', 'path' : src})
 
         if len(p.annotation_processors()) > 0:
-            genDir = p.source_gen_dir();
+            genDir = p.source_gen_dir()
             if not exists(genDir):
                 os.mkdir(genDir)
             out.element('classpathentry', {'kind' : 'src', 'path' : 'src_gen'})
@@ -2338,12 +2342,12 @@
         # Every Java program depends on the JRE
         out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.jdt.launching.JRE_CONTAINER'})
 
-        if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
+        if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
             out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.pde.core.requiredPlugins'})
 
         for dep in p.all_deps([], True):
             if dep == p:
-                continue;
+                continue
 
             if dep.isLibrary():
                 if hasattr(dep, 'eclipse.container'):
@@ -2420,7 +2424,7 @@
             out.element('name', data='net.sf.eclipsecs.core.CheckstyleBuilder')
             out.element('arguments', data='')
             out.close('buildCommand')
-        if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
+        if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
             for buildCommand in ['org.eclipse.pde.ManifestBuilder', 'org.eclipse.pde.SchemaBuilder']:
                 out.open('buildCommand')
                 out.element('name', data=buildCommand)
@@ -2428,19 +2432,19 @@
                 out.close('buildCommand')
 
         if _isAnnotationProcessorDependency(p):
-            _genEclipseBuilder(out, p, 'Jar.launch', 'archive ' + p.name, refresh = False, async = False, xmlIndent='', xmlStandalone='no')
-            _genEclipseBuilder(out, p, 'Refresh.launch', '', refresh = True, async = True)
-                       
+            _genEclipseBuilder(out, p, 'Jar.launch', 'archive ' + p.name, refresh=False, async=False, xmlIndent='', xmlStandalone='no')
+            _genEclipseBuilder(out, p, 'Refresh.launch', '', refresh=True, async=True)
+
         if projToDist.has_key(p.name):
             dist, distDeps = projToDist[p.name]
             _genEclipseBuilder(out, p, 'Create' + dist.name + 'Dist.launch', 'archive @' + dist.name, refresh=False, async=True)
-        
+
         out.close('buildSpec')
         out.open('natures')
         out.element('nature', data='org.eclipse.jdt.core.javanature')
         if exists(csConfig):
             out.element('nature', data='net.sf.eclipsecs.core.CheckstyleNature')
-        if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
+        if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
             out.element('nature', data='org.eclipse.pde.PluginNature')
         out.close('natures')
         out.close('projectDescription')
@@ -2463,7 +2467,7 @@
                     if len(p.annotation_processors()) > 0:
                         content = content.replace('org.eclipse.jdt.core.compiler.processAnnotations=disabled', 'org.eclipse.jdt.core.compiler.processAnnotations=enabled')
                     update_file(join(settingsDir, name), content)
-        
+
         if len(p.annotation_processors()) > 0:
             out = XMLDoc()
             out.open('factorypath')
@@ -2496,50 +2500,50 @@
     return p in sorted_deps(annotation_processors())
 
 def _genEclipseBuilder(dotProjectDoc, p, name, mxCommand, refresh=True, async=False, logToConsole=False, xmlIndent='\t', xmlStandalone=None):
-    launchOut = XMLDoc();
+    launchOut = XMLDoc()
     consoleOn = 'true' if logToConsole else 'false'
     launchOut.open('launchConfiguration', {'type' : 'org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType'})
-    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output',                'value': consoleOn})
+    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output', 'value': consoleOn})
     launchOut.open('mapAttribute', {'key' : 'org.eclipse.debug.core.environmentVariables'})
-    launchOut.element('mapEntry', {'key' : 'JAVA_HOME',	'value' : java().jdk})
+    launchOut.element('mapEntry', {'key' : 'JAVA_HOME', 	'value' : java().jdk})
     launchOut.close('mapAttribute')
-    
+
     if refresh:
-        launchOut.element('stringAttribute',  {'key' : 'org.eclipse.debug.core.ATTR_REFRESH_SCOPE',            'value': '${project}'})
-    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON',          'value': consoleOn})
-    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND',       'value': 'true' if async else 'false'})
-    
+        launchOut.element('stringAttribute', {'key' : 'org.eclipse.debug.core.ATTR_REFRESH_SCOPE', 'value': '${project}'})
+    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON', 'value': consoleOn})
+    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND', 'value': 'true' if async else 'false'})
+
     baseDir = dirname(dirname(os.path.abspath(__file__)))
-    
+
     cmd = 'mx.sh'
     if get_os() == 'windows':
         cmd = 'mx.cmd'
-    launchOut.element('stringAttribute',  {'key' : 'org.eclipse.ui.externaltools.ATTR_LOCATION',           'value': join(baseDir, cmd) })
-    launchOut.element('stringAttribute',  {'key' : 'org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS',    'value': 'auto,full,incremental'})
-    launchOut.element('stringAttribute',  {'key' : 'org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS',     'value': mxCommand})
-    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED','value': 'true'})
-    launchOut.element('stringAttribute',  {'key' : 'org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY',  'value': p.suite.dir})
-    
-    
+    launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_LOCATION', 'value': join(baseDir, cmd) })
+    launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS', 'value': 'auto,full,incremental'})
+    launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS', 'value': mxCommand})
+    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED', 'value': 'true'})
+    launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY', 'value': p.suite.dir})
+
+
     launchOut.close('launchConfiguration')
-    
+
     externalToolDir = join(p.dir, '.externalToolBuilders')
-    
+
     if not exists(externalToolDir):
         os.makedirs(externalToolDir)
     update_file(join(externalToolDir, name), launchOut.xml(indent=xmlIndent, standalone=xmlStandalone, newl='\n'))
-    
+
     dotProjectDoc.open('buildCommand')
     dotProjectDoc.element('name', data='org.eclipse.ui.externaltools.ExternalToolBuilder')
     dotProjectDoc.element('triggers', data='auto,full,incremental,')
     dotProjectDoc.open('arguments')
     dotProjectDoc.open('dictionary')
-    dotProjectDoc.element('key', data = 'LaunchConfigHandle')
-    dotProjectDoc.element('value', data = '<project>/.externalToolBuilders/' + name)
+    dotProjectDoc.element('key', data='LaunchConfigHandle')
+    dotProjectDoc.element('value', data='<project>/.externalToolBuilders/' + name)
     dotProjectDoc.close('dictionary')
     dotProjectDoc.open('dictionary')
-    dotProjectDoc.element('key', data = 'incclean')
-    dotProjectDoc.element('value', data = 'true')
+    dotProjectDoc.element('key', data='incclean')
+    dotProjectDoc.element('value', data='true')
     dotProjectDoc.close('dictionary')
     dotProjectDoc.close('arguments')
     dotProjectDoc.close('buildCommand')
@@ -2549,9 +2553,9 @@
     Populate the workspace's working set configuration with working sets generated from project data.
     If the workspace already contains working set definitions, the existing ones will be retained and extended.
     In case mx/env does not contain a WORKSPACE definition pointing to the workspace root directory, the Graal project root directory will be assumed.
-    If no workspace root directory can be identified, the Graal project root directory is used and the user has to place the workingsets.xml file by hand. 
+    If no workspace root directory can be identified, the Graal project root directory is used and the user has to place the workingsets.xml file by hand.
     """
-    
+
     # identify the location where to look for workingsets.xml
     wsfilename = 'workingsets.xml'
     wsroot = suite.dir
@@ -2561,7 +2565,7 @@
     if not exists(wsdir):
         wsdir = wsroot
     wspath = join(wsdir, wsfilename)
-    
+
     # gather working set info from project data
     workingSets = dict()
     for p in projects():
@@ -2572,24 +2576,24 @@
                 workingSets[w] = [p.name]
             else:
                 workingSets[w].append(p.name)
-    
+
     if exists(wspath):
         wsdoc = _copy_workingset_xml(wspath, workingSets)
     else:
         wsdoc = _make_workingset_xml(workingSets)
-    
+
     update_file(wspath, wsdoc.xml(newl='\n'))
 
 def _make_workingset_xml(workingSets):
     wsdoc = XMLDoc()
     wsdoc.open('workingSetManager')
-    
+
     for w in sorted(workingSets.keys()):
         _workingset_open(wsdoc, w)
         for p in workingSets[w]:
             _workingset_element(wsdoc, p)
         wsdoc.close('workingSet')
-    
+
     wsdoc.close('workingSetManager')
     return wsdoc
 
@@ -2598,16 +2602,16 @@
     target.open('workingSetManager')
 
     parser = xml.parsers.expat.ParserCreate()
-    
+
     class ParserState(object):
         def __init__(self):
             self.current_ws_name = 'none yet'
             self.current_ws = None
             self.seen_ws = list()
             self.seen_projects = list()
-    
+
     ps = ParserState()
-    
+
     # parsing logic
     def _ws_start(name, attributes):
         if name == 'workingSet':
@@ -2620,7 +2624,7 @@
                 ps.current_ws = None
             target.open(name, attributes)
             parser.StartElementHandler = _ws_item
-    
+
     def _ws_end(name):
         if name == 'workingSet':
             if not ps.current_ws is None:
@@ -2637,22 +2641,22 @@
                     for p in workingSets[w]:
                         _workingset_element(target, p)
                     target.close('workingSet')
-    
+
     def _ws_item(name, attributes):
         if name == 'item':
             if ps.current_ws is None:
                 target.element(name, attributes)
             else:
-                p_name = attributes['elementID'][1:] # strip off the leading '='
+                p_name = attributes['elementID'][1:]  # strip off the leading '='
                 _workingset_element(target, p_name)
                 ps.seen_projects.append(p_name)
-    
+
     # process document
     parser.StartElementHandler = _ws_start
     parser.EndElementHandler = _ws_end
     with open(wspath, 'r') as wsfile:
         parser.ParseFile(wsfile)
-    
+
     target.close('workingSetManager')
     return target
 
@@ -2661,22 +2665,19 @@
 
 def _workingset_element(wsdoc, p):
     wsdoc.element('item', {'elementID': '=' + p, 'factoryID': 'org.eclipse.jdt.ui.PersistableJavaElementFactory'})
-    
+
 def netbeansinit(args, suite=None):
     """(re)generate NetBeans project configurations"""
 
     if suite is None:
         suite = _mainSuite
 
-    def println(out, obj):
-        out.write(str(obj) + '\n')
-
     updated = False
     for p in projects():
         if p.native:
             continue
 
-        if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
+        if exists(join(p.dir, 'plugin.xml')):  # eclipse plugin project
             continue
 
         if not exists(join(p.dir, 'nbproject')):
@@ -2716,7 +2717,7 @@
         firstDep = True
         for dep in p.all_deps([], True):
             if dep == p:
-                continue;
+                continue
 
             if not dep.isLibrary():
                 n = dep.name.replace('.', '_')
@@ -2835,7 +2836,7 @@
                 print >> out, 'src.' + src + '.dir=${' + ref + '}'
 
         javacClasspath = []
-        
+
         deps = p.all_deps([], True)
         annotationProcessorOnlyDeps = []
         if len(p.annotation_processors()) > 0:
@@ -2844,12 +2845,12 @@
                 if not apDep in deps:
                     deps.append(apDep)
                     annotationProcessorOnlyDeps.append(apDep)
-        
-        annotationProcessorReferences = [];
-        
+
+        annotationProcessorReferences = []
+
         for dep in deps:
             if dep == p:
-                continue;
+                continue
 
             if dep.isLibrary():
                 if not dep.mustExist:
@@ -2871,12 +2872,12 @@
                 javacClasspath.append('${' + ref + '}')
             else:
                 annotationProcessorReferences.append('${' + ref + '}')
-                annotationProcessorReferences +=  ":\\\n    ${" + ref + "}"
+                annotationProcessorReferences += ":\\\n    ${" + ref + "}"
 
         print >> out, 'javac.classpath=\\\n    ' + (os.pathsep + '\\\n    ').join(javacClasspath)
         print >> out, 'javac.test.processorpath=${javac.test.classpath}\\\n    ' + (os.pathsep + '\\\n    ').join(annotationProcessorReferences)
         print >> out, 'javac.processorpath=${javac.classpath}\\\n    ' + (os.pathsep + '\\\n    ').join(annotationProcessorReferences)
-    
+
         updated = update_file(join(p.dir, 'nbproject', 'project.properties'), out.getvalue()) or updated
         out.close()
 
@@ -2907,7 +2908,7 @@
             rm(join(p.dir, p.name + '.jar'))
         except:
             log("Error removing {0}".format(p.name + '.jar'))
-            
+
 
 def ideinit(args, suite=None):
     """(re)generate Eclipse and NetBeans project configurations"""
@@ -2928,7 +2929,7 @@
                 projectConfigFiles = frozenset(['.classpath', 'nbproject'])
                 indicators = projectConfigFiles.intersection(files)
                 if len(indicators) != 0:
-                    if not sys.stdout.isatty() or raw_input(currentDir + ' looks like a removed project -- delete it? [yn]: ') == 'y':
+                    if not sys.stdout.isatty() or ask_yes_no(currentDir + ' looks like a removed project -- delete it', 'n'):
                         shutil.rmtree(currentDir)
                         log('Deleted ' + currentDir)
 
@@ -2990,11 +2991,13 @@
                 logv('[package-list file exists - skipping {0}]'.format(p.name))
 
 
-    def find_packages(sourceDirs, pkgs=set()):
+    def find_packages(sourceDirs, pkgs=None):
+        if pkgs is None:
+            pkgs = set()
         for sourceDir in sourceDirs:
             for root, _, files in os.walk(sourceDir):
                 if len([name for name in files if name.endswith('.java')]) != 0:
-                    pkg = root[len(sourceDir) + 1:].replace(os.sep,'.')
+                    pkg = root[len(sourceDir) + 1:].replace(os.sep, '.')
                     if len(packages) == 0 or pkg in packages:
                         if len(exclude_packages) == 0 or not pkg in exclude_packages:
                             pkgs.add(pkg)
@@ -3012,7 +3015,7 @@
         for p in projects:
             # The project must be built to ensure javadoc can find class files for all referenced classes
             build(['--no-native', '--projects', p.name])
-            
+
             pkgs = find_packages(p.source_dirs(), set())
             deps = p.all_deps([], includeLibs=False, includeSelf=False)
             links = ['-link', 'http://docs.oracle.com/javase/' + str(p.javaCompliance.value) + '/docs/api/']
@@ -3050,11 +3053,11 @@
             finally:
                 if delOverviewFile:
                     os.remove(overviewFile)
-                
+
     else:
         # The projects must be built to ensure javadoc can find class files for all referenced classes
         build(['--no-native'])
-        
+
         pkgs = set()
         sp = []
         names = []
@@ -3108,7 +3111,7 @@
             rdelimLen = 0
         old = content[lindex:rindex + rdelimLen]
         return content.replace(old, repl)
-        
+
 # Post-process an overview-summary.html file to move the
 # complete overview to the top of the page
 def _fix_overview_summary(path, topLink):
@@ -3140,7 +3143,7 @@
     assert chunk1.text, 'Could not find header section in ' + path
     assert chunk2.text, 'Could not find footer section in ' + path
 
-    content = chunk1.replace(content, '<div class="header"><div class="subTitle"><div class="block">' + topLink + chunk2.text +'</div></div></div>')
+    content = chunk1.replace(content, '<div class="header"><div class="subTitle"><div class="block">' + topLink + chunk2.text + '</div></div></div>')
     content = chunk2.replace(content, '')
 
     with open(path, 'w') as fp:
@@ -3172,9 +3175,9 @@
     if chunk1.text:
         if chunk2.text:
             repl = re.sub(r'<h2 title=(.*) Description</h2>', r'<h1 title=\1</h1>', chunk2.text, 1)
-            content = chunk1.replace(content, '<div class="header">' + repl +'</div></div>')
+            content = chunk1.replace(content, '<div class="header">' + repl + '</div></div>')
             content = chunk2.replace(content, '')
-        
+
             with open(path, 'w') as fp:
                 fp.write(content)
         else:
@@ -3236,12 +3239,12 @@
 <tbody>"""
                     color = 'row'
                     for p in projects:
-                        print >> fp2, '<tr class="{1}Color"><td class="colFirst"><a href="../{0}/javadoc/index.html", target = "_top">{0}</a></td><td class="colLast">&nbsp;</td></tr>'.format(p.name, color)
+                        print >> fp2, '<tr class="{1}Color"><td class="colFirst"><a href="../{0}/javadoc/index.html",target = "_top">{0}</a></td><td class="colLast">&nbsp;</td></tr>'.format(p.name, color)
                         color = 'row' if color == 'alt' else 'alt'
-                        
+
                     print >> fp2, '</tbody></table></div>'
                     print >> fp2, content[idx:]
-        
+
         title = args.title if args.title is not None else args.name
         javadoc(['--base', tmpbase,
                  '--unified',
@@ -3257,10 +3260,10 @@
                 if not 'version' in subprocess.check_output(['dot', '-V'], stderr=subprocess.STDOUT):
                     dotErr = 'dot -V does not print a string containing "version"'
             except subprocess.CalledProcessError as e:
-                dotErr = 'error calling "dot -V": {}'.format(e) 
+                dotErr = 'error calling "dot -V": {}'.format(e)
             except OSError as e:
                 dotErr = 'error calling "dot -V": {}'.format(e)
-                 
+
             if dotErr != None:
                 abort('cannot generate dependency graph: ' + dotErr)
 
@@ -3274,7 +3277,7 @@
                 print >> fp, 'rankdir=BT;'
                 print >> fp, 'size = "' + str(dim) + ',' + str(dim) + '";'
                 print >> fp, 'node [shape=rect, fontcolor="blue"];'
-                #print >> fp, 'edge [color="green"];'
+                # print >> fp, 'edge [color="green"];'
                 for p in projects:
                     print >> fp, '"' + p.name + '" [URL = "../' + p.name + '/javadoc/index.html", target = "_top"]'
                     for dep in p.canonical_deps():
@@ -3285,7 +3288,7 @@
                     d = p.max_depth()
                     depths.setdefault(d, list()).append(p.name)
                 print >> fp, '}'
-    
+
             run(['dot', '-Tsvg', '-o' + svg, '-Tjpg', '-o' + jpg, dot])
 
             # Post-process generated SVG to remove title elements which most browsers
@@ -3296,7 +3299,7 @@
             content = re.sub('xlink:title="[^"]*"', '', content)
             with open(svg, 'w') as fp:
                 fp.write(content)
-        
+
             # Create HTML that embeds the svg file in an <object> frame
             with open(html, 'w') as fp:
                 print >> fp, '<html><body><object data="{}.svg" type="image/svg+xml"></object></body></html>'.format(args.dot_output_base)
@@ -3347,7 +3350,7 @@
 def select_items(items, descriptions=None, allowMultiple=True):
     """
     Presents a command line interface for selecting one or more (if allowMultiple is true) items.
-    
+
     """
     if len(items) <= 1:
         return items
@@ -3371,10 +3374,10 @@
             except:
                 log('Selection contains non-numeric characters: "' + ' '.join(s) + '"')
                 continue
-            
+
             if allowMultiple and 0 in s:
                 return items
-            
+
             indexes = []
             for n in s:
                 if n not in range(1, len(items) + 1):
@@ -3391,15 +3394,15 @@
 def javap(args):
     """disassemble classes matching given pattern with javap"""
 
-    javap = java().javap
-    if not exists(javap):
-        abort('The javap executable does not exists: ' + javap)
+    javapExe = java().javap
+    if not exists(javapExe):
+        abort('The javap executable does not exists: ' + javapExe)
     else:
         candidates = findclass(args, logToConsole=False)
         if len(candidates) == 0:
             log('no matches')
         selection = select_items(candidates)
-        run([javap, '-private', '-verbose', '-classpath', classpath()] + selection)
+        run([javapExe, '-private', '-verbose', '-classpath', classpath()] + selection)
 
 def show_projects(args):
     """show all loaded projects"""
@@ -3410,6 +3413,22 @@
             for p in s.projects:
                 log('\t' + p.name)
 
+def ask_yes_no(question, default=None):
+    """"""
+    assert not default or default == 'y' or default == 'n'
+    if not sys.stdout.isatty():
+        if default:
+            return default
+        else:
+            abort("Can not answer '" + question + "?' if stdout is not a tty")
+    questionMark = '? [yn]: '
+    if default:
+        questionMark = questionMark.replace(default, default.upper())
+    answer = raw_input(question + questionMark) or default
+    while not answer:
+        answer = raw_input(question + questionMark)
+    return answer.lower().startswith('y')
+
 def add_argument(*args, **kwargs):
     """
     Define how a single command-line argument.
@@ -3422,7 +3441,7 @@
 # If any of the format args are instances of Callable, then they are called with an 'env' are before being
 # used in the call to str.format().
 # Extensions should update this table directly
-commands = {
+_commands = {
     'about': [about, ''],
     'build': [build, '[options]'],
     'checkstyle': [checkstyle, ''],
@@ -3487,8 +3506,8 @@
     command = commandAndArgs[0]
     command_args = commandAndArgs[1:]
 
-    if not commands.has_key(command):
-        hits = [c for c in commands.iterkeys() if c.startswith(command)]
+    if not _commands.has_key(command):
+        hits = [c for c in _commands.iterkeys() if c.startswith(command)]
         if len(hits) == 1:
             command = hits[0]
         elif len(hits) == 0:
@@ -3496,7 +3515,7 @@
         else:
             abort('mx: command \'{0}\' is ambiguous\n    {1}'.format(command, ' '.join(hits)))
 
-    c, _ = commands[command][:2]
+    c, _ = _commands[command][:2]
     def term_handler(signum, frame):
         abort(1)
     signal.signal(signal.SIGTERM, term_handler)
--- a/src/gpu/ptx/vm/gpu_ptx.cpp	Tue Sep 10 16:32:27 2013 -0700
+++ b/src/gpu/ptx/vm/gpu_ptx.cpp	Tue Sep 10 16:33:28 2013 -0700
@@ -29,13 +29,16 @@
 #include "utilities/ostream.hpp"
 #include "memory/allocation.hpp"
 #include "memory/allocation.inline.hpp"
+#include "kernelArguments.hpp"
 
 void * gpu::Ptx::_device_context;
+int    gpu::Ptx::_cu_device = 0;
 
 gpu::Ptx::cuda_cu_init_func_t gpu::Ptx::_cuda_cu_init;
 gpu::Ptx::cuda_cu_ctx_create_func_t gpu::Ptx::_cuda_cu_ctx_create;
-gpu::Ptx::cuda_cu_ctx_detach_func_t gpu::Ptx::_cuda_cu_ctx_detach;
+gpu::Ptx::cuda_cu_ctx_destroy_func_t gpu::Ptx::_cuda_cu_ctx_destroy;
 gpu::Ptx::cuda_cu_ctx_synchronize_func_t gpu::Ptx::_cuda_cu_ctx_synchronize;
+gpu::Ptx::cuda_cu_ctx_set_current_func_t gpu::Ptx::_cuda_cu_ctx_set_current;
 gpu::Ptx::cuda_cu_device_get_count_func_t gpu::Ptx::_cuda_cu_device_get_count;
 gpu::Ptx::cuda_cu_device_get_name_func_t gpu::Ptx::_cuda_cu_device_get_name;
 gpu::Ptx::cuda_cu_device_get_func_t gpu::Ptx::_cuda_cu_device_get;
@@ -44,6 +47,8 @@
 gpu::Ptx::cuda_cu_launch_kernel_func_t gpu::Ptx::_cuda_cu_launch_kernel;
 gpu::Ptx::cuda_cu_module_get_function_func_t gpu::Ptx::_cuda_cu_module_get_function;
 gpu::Ptx::cuda_cu_module_load_data_ex_func_t gpu::Ptx::_cuda_cu_module_load_data_ex;
+gpu::Ptx::cuda_cu_memcpy_dtoh_func_t gpu::Ptx::_cuda_cu_memcpy_dtoh;
+gpu::Ptx::cuda_cu_memfree_func_t gpu::Ptx::_cuda_cu_memfree;
 
 void gpu::probe_linkage() {
 #if defined(__APPLE__) || defined(LINUX)
@@ -67,9 +72,9 @@
   }
 }
 
-bool gpu::execute_kernel(address kernel, JavaCallArguments * jca) {
+bool gpu::execute_kernel(address kernel, PTXKernelArguments & ptxka, JavaValue& ret) {
   if (gpu::has_gpu_linkage()) {
-    return (gpu::Ptx::execute_kernel(kernel, jca));
+    return (gpu::Ptx::execute_kernel(kernel, ptxka, ret));
   } else {
     return false;
   }
@@ -83,7 +88,7 @@
     tty->print_cr("Failed to initialize CUDA device");
     return false;
   }
- 
+
   if (TraceGPUInteraction) {
     tty->print_cr("CUDA driver initialization: Success");
   }
@@ -104,12 +109,11 @@
   if (TraceGPUInteraction) {
     tty->print_cr("[CUDA] Number of compute-capable devices found: %d", device_count);
   }
-  
+
   /* Get the handle to the first compute device */
   int device_id = 0;
   /* Compute-capable device handle */
-  int cu_device = 0;
-  status = _cuda_cu_device_get(&cu_device, device_id);
+  status = _cuda_cu_device_get(&_cu_device, device_id);
 
   if (status != GRAAL_CUDA_SUCCESS) {
     tty->print_cr("[CUDA] Failed to get handle of first compute-capable device i.e., the one at ordinal: %d", device_id);
@@ -122,42 +126,42 @@
 
   /* Get device attributes */
   int minor, major, unified_addressing;
-  status = _cuda_cu_device_get_attribute(&minor, GRAAL_CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, cu_device);
+  status = _cuda_cu_device_get_attribute(&minor, GRAAL_CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, _cu_device);
 
   if (status != GRAAL_CUDA_SUCCESS) {
-    tty->print_cr("[CUDA] Failed to get minor attribute of device: %d", cu_device);
+    tty->print_cr("[CUDA] Failed to get minor attribute of device: %d", _cu_device);
     return false;
   }
 
-  status = _cuda_cu_device_get_attribute(&major, GRAAL_CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cu_device);
+  status = _cuda_cu_device_get_attribute(&major, GRAAL_CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, _cu_device);
 
   if (status != GRAAL_CUDA_SUCCESS) {
-    tty->print_cr("[CUDA] Failed to get major attribute of device: %d", cu_device);
+    tty->print_cr("[CUDA] Failed to get major attribute of device: %d", _cu_device);
     return false;
   }
 
   if (TraceGPUInteraction) {
-    tty->print_cr("[CUDA] Compatibility version of device %d: %d.%d", cu_device, major, minor);
+    tty->print_cr("[CUDA] Compatibility version of device %d: %d.%d", _cu_device, major, minor);
   }
 
-  status = _cuda_cu_device_get_attribute(&unified_addressing, GRAAL_CU_DEVICE_ATTRIBUTE_UNIFIED_ADDRESSING, cu_device);
+  status = _cuda_cu_device_get_attribute(&unified_addressing, GRAAL_CU_DEVICE_ATTRIBUTE_UNIFIED_ADDRESSING, _cu_device);
 
   if (status != GRAAL_CUDA_SUCCESS) {
-    tty->print_cr("[CUDA] Failed to query unified addressing mode of device: %d", cu_device);
+    tty->print_cr("[CUDA] Failed to query unified addressing mode of device: %d", _cu_device);
     return false;
   }
 
   if (TraceGPUInteraction) {
-    tty->print_cr("[CUDA] Unified addressing support on device %d: %d", cu_device, unified_addressing);
+    tty->print_cr("[CUDA] Unified addressing support on device %d: %d", _cu_device, unified_addressing);
   }
 
 
   /* Get device name */
   char device_name[256];
-  status = _cuda_cu_device_get_name(device_name, 256, cu_device);
+  status = _cuda_cu_device_get_name(device_name, 256, _cu_device);
 
   if (status != GRAAL_CUDA_SUCCESS) {
-    tty->print_cr("[CUDA] Failed to get name of device: %d", cu_device);
+    tty->print_cr("[CUDA] Failed to get name of device: %d", _cu_device);
     return false;
   }
 
@@ -165,18 +169,6 @@
     tty->print_cr("[CUDA] Using %s", device_name);
   }
 
-  /* Create CUDA context */
-  status = _cuda_cu_ctx_create(&_device_context, 0, cu_device);
-
-  if (status != GRAAL_CUDA_SUCCESS) {
-    tty->print_cr("[CUDA] Failed to create CUDA context for device: %d", cu_device);
-    return false;
-  }
-
-  if (TraceGPUInteraction) {
-    tty->print_cr("[CUDA] Success: Created context for device: %d", cu_device);
-  }
-
   return true;
 }
 
@@ -204,6 +196,29 @@
   jit_options[2] = GRAAL_CU_JIT_MAX_REGISTERS;
   jit_option_values[2] = (void *)(size_t)jit_register_count;
 
+  /* Create CUDA context to compile and execute the kernel */
+  int status = _cuda_cu_ctx_create(&_device_context, 0, _cu_device);
+
+  if (status != GRAAL_CUDA_SUCCESS) {
+    tty->print_cr("[CUDA] Failed to create CUDA context for device: %d", _cu_device);
+    return NULL;
+  }
+
+  if (TraceGPUInteraction) {
+    tty->print_cr("[CUDA] Success: Created context for device: %d", _cu_device);
+  }
+
+  status = _cuda_cu_ctx_set_current(_device_context);
+
+  if (status != GRAAL_CUDA_SUCCESS) {
+    tty->print_cr("[CUDA] Failed to set current context for device: %d", _cu_device);
+    return NULL;
+  }
+
+  if (TraceGPUInteraction) {
+    tty->print_cr("[CUDA] Success: Set current context for device: %d", _cu_device);
+  }
+
   if (TraceGPUInteraction) {
     tty->print_cr("[CUDA] PTX Kernel\n%s", code);
     tty->print_cr("[CUDA] Function name : %s", name);
@@ -211,13 +226,13 @@
   }
 
   /* Load module's data with compiler options */
-  int status = _cuda_cu_module_load_data_ex(&cu_module, code, jit_num_options,
+  status = _cuda_cu_module_load_data_ex(&cu_module, (void*) code, jit_num_options,
                                             jit_options, (void **)jit_option_values);
   if (status != GRAAL_CUDA_SUCCESS) {
     if (status == GRAAL_CUDA_ERROR_NO_BINARY_FOR_GPU) {
       tty->print_cr("[CUDA] Check for malformed PTX kernel or incorrect PTX compilation options");
     }
-    tty->print_cr("[CUDA] *** Error (%d) Failed to load module data with online compiler options for method %s", 
+    tty->print_cr("[CUDA] *** Error (%d) Failed to load module data with online compiler options for method %s",
                   status, name);
     return NULL;
   }
@@ -238,10 +253,11 @@
   if (TraceGPUInteraction) {
     tty->print_cr("[CUDA] Got function handle for %s", name);
   }
+
   return cu_function;
 }
 
-bool gpu::Ptx::execute_kernel(address kernel, JavaCallArguments * jca) {
+bool gpu::Ptx::execute_kernel(address kernel, PTXKernelArguments &ptxka, JavaValue &ret) {
   // grid dimensionality
   unsigned int gridX = 1;
   unsigned int gridY = 1;
@@ -251,15 +267,12 @@
   unsigned int blockX = 1;
   unsigned int blockY = 1;
   unsigned int blockZ = 1;
-  
-  int *cu_function = (int *)kernel;
+
+  struct CUfunc_st* cu_function = (struct CUfunc_st*) kernel;
 
-  char * paramBuffer = (char *) jca->parameters();
-  size_t paramBufferSz = (size_t) jca->size_of_parameters();
-
-  void * config[] = {
-    GRAAL_CU_LAUNCH_PARAM_BUFFER_POINTER, paramBuffer,
-    GRAAL_CU_LAUNCH_PARAM_BUFFER_SIZE, &paramBufferSz,
+  void * config[5] = {
+    GRAAL_CU_LAUNCH_PARAM_BUFFER_POINTER, ptxka._kernelArgBuffer,
+    GRAAL_CU_LAUNCH_PARAM_BUFFER_SIZE, &(ptxka._bufferOffset),
     GRAAL_CU_LAUNCH_PARAM_END
   };
 
@@ -270,10 +283,11 @@
   if (TraceGPUInteraction) {
     tty->print_cr("[CUDA] launching kernel");
   }
+
   int status = _cuda_cu_launch_kernel(cu_function,
                                       gridX, gridY, gridZ,
                                       blockX, blockY, blockZ,
-                                      0, NULL, NULL, config);
+                                      0, NULL, NULL, (void **) &config);
   if (status != GRAAL_CUDA_SUCCESS) {
     tty->print_cr("[CUDA] Failed to launch kernel");
     return false;
@@ -282,7 +296,72 @@
   if (TraceGPUInteraction) {
     tty->print_cr("[CUDA] Success: Kernel Launch");
   }
-  return status == 0;  // GRAAL_CUDA_SUCCESS
+
+  status = _cuda_cu_ctx_synchronize();
+
+  if (status != GRAAL_CUDA_SUCCESS) {
+    tty->print_cr("[CUDA] Failed to synchronize launched kernel (%d)", status);
+    return false;
+  }
+
+  if (TraceGPUInteraction) {
+    tty->print_cr("[CUDA] Success: Synchronized launch kernel");
+  }
+
+
+  // Get the result. TODO: Move this code to get_return_oop()
+  BasicType return_type = ptxka.get_ret_type();
+  switch (return_type) {
+     case T_INT :
+       {
+         int return_val;
+         status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._return_value_ptr, T_INT_BYTE_SIZE);
+         if (status != GRAAL_CUDA_SUCCESS) {
+           tty->print_cr("[CUDA] *** Error (%d) Failed to copy value to device argument", status);
+           return false;
+         }
+         ret.set_jint(return_val);
+       }
+       break;
+     case T_LONG :
+       {
+         long return_val;
+         status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._return_value_ptr, T_LONG_BYTE_SIZE);
+         if (status != GRAAL_CUDA_SUCCESS) {
+           tty->print_cr("[CUDA] *** Error (%d) Failed to copy value to device argument", status);
+           return false;
+         }
+         ret.set_jlong(return_val);
+       }
+       break;
+     default:
+       tty->print_cr("[CUDA] TODO *** Unhandled return type");
+  }
+
+
+  // Free device memory allocated for result
+  status = gpu::Ptx::_cuda_cu_memfree(ptxka._return_value_ptr);
+  if (status != GRAAL_CUDA_SUCCESS) {
+    tty->print_cr("[CUDA] *** Error (%d) Failed to free device memory of return value", status);
+    return false;
+  }
+
+  if (TraceGPUInteraction) {
+    tty->print_cr("[CUDA] Success: Freed device memory of return value");
+  }
+
+  // Destroy context
+  status = gpu::Ptx::_cuda_cu_ctx_destroy(_device_context);
+  if (status != GRAAL_CUDA_SUCCESS) {
+    tty->print_cr("[CUDA] *** Error (%d) Failed to destroy context", status);
+    return false;
+  }
+
+  if (TraceGPUInteraction) {
+    tty->print_cr("[CUDA] Success: Destroy context");
+  }
+
+  return (status == GRAAL_CUDA_SUCCESS);
 }
 
 #if defined(LINUX)
@@ -299,16 +378,18 @@
   if (cuda_library_name != NULL) {
     char *buffer = (char*)malloc(STD_BUFFER_SIZE);
     void *handle = os::dll_load(cuda_library_name, buffer, STD_BUFFER_SIZE);
-	free(buffer);
+        free(buffer);
     if (handle != NULL) {
       _cuda_cu_init =
         CAST_TO_FN_PTR(cuda_cu_init_func_t, os::dll_lookup(handle, "cuInit"));
       _cuda_cu_ctx_create =
         CAST_TO_FN_PTR(cuda_cu_ctx_create_func_t, os::dll_lookup(handle, "cuCtxCreate"));
-      _cuda_cu_ctx_detach =
-        CAST_TO_FN_PTR(cuda_cu_ctx_detach_func_t, os::dll_lookup(handle, "cuCtxDetach"));
+      _cuda_cu_ctx_destroy =
+        CAST_TO_FN_PTR(cuda_cu_ctx_destroy_func_t, os::dll_lookup(handle, "cuCtxDestroy"));
       _cuda_cu_ctx_synchronize =
         CAST_TO_FN_PTR(cuda_cu_ctx_synchronize_func_t, os::dll_lookup(handle, "cuCtxSynchronize"));
+      _cuda_cu_ctx_set_current =
+        CAST_TO_FN_PTR(cuda_cu_ctx_set_current_func_t, os::dll_lookup(handle, "cuCtxSetCurrent"));
       _cuda_cu_device_get_count =
         CAST_TO_FN_PTR(cuda_cu_device_get_count_func_t, os::dll_lookup(handle, "cuDeviceGetCount"));
       _cuda_cu_device_get_name =
@@ -325,6 +406,15 @@
         CAST_TO_FN_PTR(cuda_cu_module_load_data_ex_func_t, os::dll_lookup(handle, "cuModuleLoadDataEx"));
       _cuda_cu_launch_kernel =
         CAST_TO_FN_PTR(cuda_cu_launch_kernel_func_t, os::dll_lookup(handle, "cuLaunchKernel"));
+      _cuda_cu_memalloc =
+        CAST_TO_FN_PTR(cuda_cu_memalloc_func_t, os::dll_lookup(handle, "cuMemAlloc"));
+      _cuda_cu_memfree =
+        CAST_TO_FN_PTR(cuda_cu_memfree_func_t, os::dll_lookup(handle, "cuMemFree"));
+      _cuda_cu_memcpy_htod =
+        CAST_TO_FN_PTR(cuda_cu_memcpy_htod_func_t, os::dll_lookup(handle, "cuMemcpyHtoD"));
+      _cuda_cu_memcpy_dtoh =
+        CAST_TO_FN_PTR(cuda_cu_memcpy_dtoh_func_t, os::dll_lookup(handle, "cuMemcpyDtoH"));
+
       if (TraceGPUInteraction) {
         tty->print_cr("[CUDA] Success: library linkage");
       }
@@ -340,4 +430,3 @@
   tty->print_cr("Failed to find CUDA linkage");
   return false;
 }
-
--- a/src/gpu/ptx/vm/gpu_ptx.hpp	Tue Sep 10 16:32:27 2013 -0700
+++ b/src/gpu/ptx/vm/gpu_ptx.hpp	Tue Sep 10 16:33:28 2013 -0700
@@ -25,7 +25,7 @@
 #ifndef GPU_PTX_HPP
 #define GPU_PTX_HPP
 
-/* 
+/*
  * Some useful macro definitions from publicly available cuda.h.
  * These definitions are for convenience.
  */
@@ -44,7 +44,7 @@
  * End of array terminator for the extra parameter to
  * ::cuLaunchKernel
  */
-#define GRAAL_CU_LAUNCH_PARAM_END            ((void *) 0x00)
+#define GRAAL_CU_LAUNCH_PARAM_END            ((void*) 0x00)
 
 /**
  * Indicator that the next value in the  extra parameter to
@@ -55,7 +55,7 @@
  *  extra array, then ::GRAAL_CU_LAUNCH_PARAM_BUFFER_POINTER will have no
  * effect.
  */
-#define GRAAL_CU_LAUNCH_PARAM_BUFFER_POINTER ((void *) 0x01)
+#define GRAAL_CU_LAUNCH_PARAM_BUFFER_POINTER ((void*) 0x01)
 
 /**
  * Indicator that the next value in the  extra parameter to
@@ -65,7 +65,7 @@
  * in the extra array if the value associated with
  * ::GRAAL_CU_LAUNCH_PARAM_BUFFER_SIZE is not zero.
  */
-#define GRAAL_CU_LAUNCH_PARAM_BUFFER_SIZE    ((void *) 0x02)
+#define GRAAL_CU_LAUNCH_PARAM_BUFFER_SIZE    ((void*) 0x02)
 
 class Ptx {
   friend class gpu;
@@ -74,28 +74,40 @@
   static bool probe_linkage();
   static bool initialize_gpu();
   static void * generate_kernel(unsigned char *code, int code_len, const char *name);
-  static bool execute_kernel(address kernel, JavaCallArguments *);
-  
+  static bool execute_kernel(address kernel, PTXKernelArguments & ka, JavaValue &ret);
+public:
+#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64)
+  typedef unsigned long long CUdeviceptr;
+#else
+  typedef unsigned int CUdeviceptr;
+#endif
+
 private:
   typedef int (*cuda_cu_init_func_t)(unsigned int);
-  typedef int (*cuda_cu_ctx_create_func_t)(void *, int, int);
-  typedef int (*cuda_cu_ctx_detach_func_t)(int *);
-  typedef int (*cuda_cu_ctx_synchronize_func_t)(int *);
-  typedef int (*cuda_cu_device_get_count_func_t)(int *);
-  typedef int (*cuda_cu_device_get_name_func_t)(char *, int, int);
-  typedef int (*cuda_cu_device_get_func_t)(int *, int);
-  typedef int (*cuda_cu_device_compute_capability_func_t)(int *, int *, int);
-  typedef int (*cuda_cu_device_get_attribute_func_t)(int *, int, int);
-  typedef int (*cuda_cu_launch_kernel_func_t)(void *,
+  typedef int (*cuda_cu_ctx_create_func_t)(void*, int, int);
+  typedef int (*cuda_cu_ctx_destroy_func_t)(void*);
+  typedef int (*cuda_cu_ctx_synchronize_func_t)(void);
+  typedef int (*cuda_cu_ctx_set_current_func_t)(void*);
+  typedef int (*cuda_cu_device_get_count_func_t)(int*);
+  typedef int (*cuda_cu_device_get_name_func_t)(char*, int, int);
+  typedef int (*cuda_cu_device_get_func_t)(int*, int);
+  typedef int (*cuda_cu_device_compute_capability_func_t)(int*, int*, int);
+  typedef int (*cuda_cu_device_get_attribute_func_t)(int*, int, int);
+  typedef int (*cuda_cu_launch_kernel_func_t)(struct CUfunc_st*,
                                               unsigned int, unsigned int, unsigned int,
                                               unsigned int, unsigned int, unsigned int,
-                                              unsigned int, void *, void **, void **);
-  typedef int (*cuda_cu_module_get_function_func_t)(void *, void *, const char *);
-  typedef int (*cuda_cu_module_load_data_ex_func_t)(void *, void *, unsigned int, void *, void **);
+                                              unsigned int, void*, void**, void**);
+  typedef int (*cuda_cu_module_get_function_func_t)(void*, void*, const char*);
+  typedef int (*cuda_cu_module_load_data_ex_func_t)(void*, void*, unsigned int, void*, void**);
+  typedef int (*cuda_cu_memalloc_func_t)(void*, size_t);
+  typedef int (*cuda_cu_memfree_func_t)(gpu::Ptx::CUdeviceptr);
+  typedef int (*cuda_cu_memcpy_htod_func_t)(gpu::Ptx::CUdeviceptr, const void*, unsigned int);
+  typedef int (*cuda_cu_memcpy_dtoh_func_t)(const void*, gpu::Ptx::CUdeviceptr,  unsigned int);
 
+public:
   static cuda_cu_init_func_t                      _cuda_cu_init;
   static cuda_cu_ctx_create_func_t                _cuda_cu_ctx_create;
-  static cuda_cu_ctx_detach_func_t                _cuda_cu_ctx_detach;
+  static cuda_cu_ctx_destroy_func_t               _cuda_cu_ctx_destroy;
   static cuda_cu_ctx_synchronize_func_t           _cuda_cu_ctx_synchronize;
   static cuda_cu_device_get_count_func_t          _cuda_cu_device_get_count;
   static cuda_cu_device_get_name_func_t           _cuda_cu_device_get_name;
@@ -105,8 +117,14 @@
   static cuda_cu_launch_kernel_func_t             _cuda_cu_launch_kernel;
   static cuda_cu_module_get_function_func_t       _cuda_cu_module_get_function;
   static cuda_cu_module_load_data_ex_func_t       _cuda_cu_module_load_data_ex;
+  static cuda_cu_memalloc_func_t                  _cuda_cu_memalloc;
+  static cuda_cu_memfree_func_t                   _cuda_cu_memfree;
+  static cuda_cu_memcpy_htod_func_t               _cuda_cu_memcpy_htod;
+  static cuda_cu_memcpy_dtoh_func_t               _cuda_cu_memcpy_dtoh;
+  static cuda_cu_ctx_set_current_func_t           _cuda_cu_ctx_set_current;
 
 protected:
-  static void * _device_context;
+  static void* _device_context;
+  static int _cu_device;
 };
 #endif // GPU_PTX_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gpu/ptx/vm/kernelArguments.cpp	Tue Sep 10 16:33:28 2013 -0700
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "kernelArguments.hpp"
+#include "runtime/javaCalls.hpp"
+
+gpu::Ptx::cuda_cu_memalloc_func_t gpu::Ptx::_cuda_cu_memalloc;
+gpu::Ptx::cuda_cu_memcpy_htod_func_t gpu::Ptx::_cuda_cu_memcpy_htod;
+
+// Get next java argument
+oop PTXKernelArguments::next_arg(BasicType expectedType) {
+  assert(_index < _args->length(), "out of bounds");
+  oop arg=((objArrayOop) (_args))->obj_at(_index++);
+  assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch");
+  return arg;
+}
+
+void PTXKernelArguments::do_int()    { 
+  // If the parameter is a return value, 
+  if (is_return_type()) {
+    // Allocate device memory for T_INT return value pointer on device. Size in bytes
+    int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_INT_BYTE_SIZE);
+    if (status != GRAAL_CUDA_SUCCESS) {
+      tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
+      _success = false;
+      return;
+    }
+    // Push _return_value_ptr to _kernelBuffer
+    *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr;
+    _bufferOffset += sizeof(_return_value_ptr);
+  }
+  else {
+    // Get the next java argument and its value which should be a T_INT
+    oop arg = next_arg(T_INT);
+    // Copy the java argument value to kernelArgBuffer
+    jvalue intval;
+    if (java_lang_boxing_object::get_value(arg, &intval) != T_INT) {
+      tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_INT");
+      _success = false;
+      return;
+    }
+    *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = intval.i;
+    _bufferOffset += sizeof(intval.i);
+  }
+  return;
+}
+
+void PTXKernelArguments::do_long()    { 
+  // If the parameter is a return value, 
+  if (is_return_type()) {
+    // Allocate device memory for T_LONG return value pointer on device. Size in bytes
+    int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_LONG_BYTE_SIZE);
+    if (status != GRAAL_CUDA_SUCCESS) {
+      tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
+      _success = false;
+      return;
+    }
+    // Push _return_value_ptr to _kernelBuffer
+    *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr;
+    _bufferOffset += sizeof(_return_value_ptr);
+  }
+  else {
+    // Get the next java argument and its value which should be a T_LONG
+    oop arg = next_arg(T_LONG);
+    // Copy the java argument value to kernelArgBuffer
+    jvalue val;
+    if (java_lang_boxing_object::get_value(arg, &val) != T_LONG) {
+      tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_LONG");
+      _success = false;
+      return;
+    }
+    *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.j;
+    _bufferOffset += sizeof(val.j);
+  }
+  return;
+}
+
+void PTXKernelArguments::do_byte()    { 
+  // If the parameter is a return value, 
+  if (is_return_type()) {
+    // Allocate device memory for T_BYTE return value pointer on device. Size in bytes
+    int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_BYTE_SIZE);
+    if (status != GRAAL_CUDA_SUCCESS) {
+      tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status);
+      _success = false;
+      return;
+    }
+    // Push _return_value_ptr to _kernelBuffer
+    *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr;
+    _bufferOffset += sizeof(_return_value_ptr);
+  }
+  else {
+    // Get the next java argument and its value which should be a T_BYTE
+    oop arg = next_arg(T_BYTE);
+    // Copy the java argument value to kernelArgBuffer
+    jvalue val;
+    if (java_lang_boxing_object::get_value(arg, &val) != T_BYTE) {
+      tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_BYTE");
+      _success = false;
+      return;
+    }
+    *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.b;
+    _bufferOffset += sizeof(val.b);
+  }
+  return;
+}
+
+// TODO implement other do_*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gpu/ptx/vm/kernelArguments.hpp	Tue Sep 10 16:33:28 2013 -0700
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef KERNEL_ARGUMENTS_PTX_HPP
+#define KERNEL_ARGUMENTS_PTX_HPP
+
+#include "runtime/gpu.hpp"
+#include "runtime/signature.hpp"
+
+#define T_BYTE_SIZE       1
+#define T_INT_BYTE_SIZE   4
+#define T_LONG_BYTE_SIZE  8
+
+class PTXKernelArguments : public SignatureIterator {
+public:
+  // Buffer holding CUdeviceptr values that represent the kernel arguments
+  char _kernelArgBuffer[1024];
+  // Current offset into _kernelArgBuffer
+  size_t _bufferOffset;
+  gpu::Ptx::CUdeviceptr _return_value_ptr;
+private:
+  // Array of java argument oops
+  arrayOop _args;
+  // Current index into _args
+  int _index;
+  // Flag to indicate successful creation of kernel argument buffer
+  bool _success;
+  // Get next java argument
+  oop next_arg(BasicType expectedType);
+
+ public:
+  PTXKernelArguments(Symbol* signature, arrayOop args, bool is_static) : SignatureIterator(signature) {
+    this->_return_type = T_ILLEGAL;
+    _index = 0;
+    _args = args;
+    _success = true;
+    _bufferOffset = 0;
+    _return_value_ptr = 0;
+    if (!is_static) {
+      // TODO : Create a device argument for receiver object and add it to _kernelBuffer
+      tty->print_cr("{CUDA] ****** TODO: Support for execution of non-static java methods not implemented yet.");
+    }
+    // Iterate over the entire signature
+    iterate();
+    assert((_success && (_index == args->length())), "arg count mismatch with signature");
+  }
+
+  inline char* device_argument_buffer() {
+    return _kernelArgBuffer;
+  }
+
+  inline size_t device_argument_buffer_size() {
+    return _bufferOffset;
+  }
+
+  // Get the return oop value
+  oop get_return_oop();
+
+  // get device return value ptr
+  gpu::Ptx::CUdeviceptr get_return_value_ptr() {
+      return _return_value_ptr;
+  }
+
+  
+  void do_byte();
+  void do_int();
+  void do_long();
+
+  inline void do_bool()   {
+    /* TODO : To be implemented */ 
+    guarantee(false, "NYI");
+  }
+  inline void do_char()   {
+    /* TODO : To be implemented */ 
+    guarantee(false, "NYI");
+  }
+  inline void do_short()  {
+    /* TODO : To be implemented */ 
+    guarantee(false, "NYI");
+  }
+  inline void do_float()  {
+    /* TODO : To be implemented */ 
+    guarantee(false, "NYI");
+  }
+  inline void do_double() {
+    /* TODO : To be implemented */ 
+    guarantee(false, "NYI");
+  }
+
+  inline void do_object() {
+    /* TODO : To be implemented */ 
+    guarantee(false, "NYI");
+  }
+  inline void do_object(int begin, int end) {
+    /* TODO : To be implemented */ 
+    guarantee(false, "NYI");
+  }
+  inline void do_array(int begin, int end)  {
+    /* TODO : To be implemented */ 
+    guarantee(false, "NYI");
+  }
+  inline void do_void() {
+    /* TODO : To be implemented */ 
+    guarantee(false, "NYI");
+  }
+};
+
+#endif  // KERNEL_ARGUMENTS_HPP
--- a/src/os_gpu/linux_ptx/vm/gpu_linux.cpp	Tue Sep 10 16:32:27 2013 -0700
+++ b/src/os_gpu/linux_ptx/vm/gpu_linux.cpp	Tue Sep 10 16:33:28 2013 -0700
@@ -39,7 +39,6 @@
  */
 
 static unsigned int nvidia_vendor_id = 0x10de;
-static unsigned int nvidia_gk110_dev_id = 0x1005;
 
 bool gpu::Linux::probe_gpu() {
   /* 
@@ -62,7 +61,7 @@
   while (fgets(contents, sizeof(contents)-1, pci_devices)) {
     sscanf(contents, "%04x%04x%04x", &bus_num_devfn_ign, &vendor, &device);
     /* Break after finding the first CUDA device. */
-    if ((vendor == nvidia_vendor_id) && (device = nvidia_gk110_dev_id)) {
+    if (vendor == nvidia_vendor_id) {
       cuda_device_exists = true;
       if (TraceGPUInteraction) {
         tty->print_cr("Found supported nVidia CUDA device vendor : 0x%04x device 0x%04x", vendor, device);
--- a/src/share/vm/classfile/vmSymbols.hpp	Tue Sep 10 16:32:27 2013 -0700
+++ b/src/share/vm/classfile/vmSymbols.hpp	Tue Sep 10 16:33:28 2013 -0700
@@ -356,6 +356,7 @@
   template(compileMethod_signature,               "(JLcom/oracle/graal/hotspot/meta/HotSpotResolvedObjectType;IZ)V")                  \
   template(setOption_name,                        "setOption")                                                                        \
   template(setOption_signature,                   "(Ljava/lang/String;)Z")                                                            \
+  template(finalizeOptions_name,                  "finalizeOptions")                                                                  \
   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;") \
   template(createSignature_name,                  "createSignature")                                                                  \
--- a/src/share/vm/graal/graalCompiler.cpp	Tue Sep 10 16:32:27 2013 -0700
+++ b/src/share/vm/graal/graalCompiler.cpp	Tue Sep 10 16:33:28 2013 -0700
@@ -95,6 +95,8 @@
         vm_abort(false);
       }
     }
+    VMToCompiler::finalizeOptions(CITime);
+
     if (UseCompiler) {
       VMToCompiler::startCompiler(BootstrapGraal);
       _initialized = true;
--- a/src/share/vm/graal/graalCompilerToGPU.cpp	Tue Sep 10 16:32:27 2013 -0700
+++ b/src/share/vm/graal/graalCompilerToGPU.cpp	Tue Sep 10 16:33:28 2013 -0700
@@ -24,13 +24,11 @@
 #include "precompiled.hpp"
 
 #include "graal/graalCompiler.hpp"
-#include "runtime/javaCalls.hpp"
-#include "graal/graalCompilerToVM.hpp"
 #include "graal/graalEnv.hpp"
 #include "graal/graalJavaAccess.hpp"
 #include "runtime/gpu.hpp"
 #include "runtime/javaCalls.hpp"
-
+# include "ptx/vm/kernelArguments.hpp"
 
 // Entry to native method implementation that transitions current thread to '_thread_in_vm'.
 #define C2V_VMENTRY(result_type, name, signature) \
@@ -81,27 +79,28 @@
   nmethod* nm = (nmethod*) (address) nmethodValue;
   methodHandle mh = nm->method();
   Symbol* signature = mh->signature();
-  JavaCallArguments jca(mh->size_of_parameters());
-
-  JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static());
-  JavaValue result(jap.get_ret_type());
-  jca.set_alternative_target(nm);
 
   // start value is the kernel
   jlong startValue = HotSpotInstalledCode::codeStart(hotspotInstalledCode);
 
-  if (!gpu::execute_kernel((address)startValue, &jca)) {
+  PTXKernelArguments ptxka(signature, (arrayOop) JNIHandles::resolve(args), mh->is_static());
+  JavaValue result(ptxka.get_ret_type());
+  if (!gpu::execute_kernel((address)startValue, ptxka, result)) {
     return NULL;
   }
 
-  if (jap.get_ret_type() == T_VOID) {
+  if (ptxka.get_ret_type() == T_VOID) {
     return NULL;
-  } else if (jap.get_ret_type() == T_OBJECT || jap.get_ret_type() == T_ARRAY) {
+  } else if (ptxka.get_ret_type() == T_OBJECT || ptxka.get_ret_type() == T_ARRAY) {
     return JNIHandles::make_local((oop) result.get_jobject());
   } else {
-    oop o = java_lang_boxing_object::create(jap.get_ret_type(), (jvalue *) result.get_value_addr(), CHECK_NULL);
+    oop o = java_lang_boxing_object::create(ptxka.get_ret_type(), (jvalue *) result.get_value_addr(), CHECK_NULL);
+    if (TraceGPUInteraction) {
+      tty->print_cr("GPU execution returned %d", result.get_jint());
+    }
     return JNIHandles::make_local(o);
   }
+
 C2V_END
 
 C2V_VMENTRY(jboolean, deviceInit, (JNIEnv *env, jobject))
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Tue Sep 10 16:32:27 2013 -0700
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Tue Sep 10 16:33:28 2013 -0700
@@ -64,39 +64,24 @@
   ResourceMark rm;
 
   int code_size = method->code_size();
-  jbyte* reconstituted_code = NULL;
+  jbyte* reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size);
+
+  guarantee(method->method_holder()->is_rewritten(), "Method's holder should be rewritten");
+  // iterate over all bytecodes and replace non-Java bytecodes
 
-  // replace all breakpoints - must be done before undoing any rewriting
-  if (method->number_of_breakpoints() > 0) {
-    reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size);
-    memcpy(reconstituted_code, (jbyte *) method->code_base(), code_size);
-    BreakpointInfo* bp = InstanceKlass::cast(method->method_holder())->breakpoints();
-    for (; bp != NULL; bp = bp->next()) {
-      if (bp->match(method())) {
-        jbyte code = bp->orig_bytecode();
-        reconstituted_code[bp->bci()] = code;
-      }
-    }
-  }
+  for (BytecodeStream s(method); s.next() != Bytecodes::_illegal; ) {
+    Bytecodes::Code code = s.code();
+    Bytecodes::Code raw_code = s.raw_code();
+    int bci = s.bci();
+    int len = s.instruction_size();
 
-  // iterate over all bytecodes and replace non-Java bytecodes
-  if (RewriteBytecodes || RewriteFrequentPairs || InstanceKlass::cast(method->method_holder())->is_rewritten()) {
-    if (reconstituted_code == NULL) {
-      reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size);
-      memcpy(reconstituted_code, (jbyte *) method->code_base(), code_size);
+    // Restore original byte code.
+    reconstituted_code[bci] = (jbyte) (s.is_wide()? Bytecodes::_wide : code);
+    if (len > 1) {
+      memcpy(&reconstituted_code[bci+1], s.bcp()+1, len-1);
     }
 
-    for (BytecodeStream s(method); s.next() != Bytecodes::_illegal; ) {
-      Bytecodes::Code code = s.code();
-      Bytecodes::Code raw_code = s.raw_code();
-      int bci = s.bci();
-
-      // Restore original byte code.  The Bytecodes::is_java_code check
-      // also avoids overwriting wide bytecodes.
-      if (!Bytecodes::is_java_code(raw_code)) {
-        reconstituted_code[bci] = (jbyte) code;
-      }
-
+    if (len > 1) {
       // Restore the big-endian constant pool indexes.
       // Cf. Rewriter::scan_method
       switch (code) {
@@ -141,11 +126,7 @@
     }
   }
 
-  if (reconstituted_code == NULL) {
-    env->SetByteArrayRegion(result, 0, code_size, (jbyte *) method->code_base());
-  } else {
-    env->SetByteArrayRegion(result, 0, code_size, reconstituted_code);
-  }
+  env->SetByteArrayRegion(result, 0, code_size, reconstituted_code);
 
   return result;
 C2V_END
@@ -573,6 +554,12 @@
   return InstanceKlass::cast(klass)->is_initialized();
 C2V_END
 
+C2V_VMENTRY(jboolean, isTypeLinked,(JNIEnv *, jobject, jobject hotspot_klass))
+  Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass));
+  assert(klass != NULL, "method must not be called for primitive types");
+  return InstanceKlass::cast(klass)->is_linked();
+C2V_END
+
 C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv *, jobject, jobject hotspot_klass))
   Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass));
   assert(klass != NULL, "method must not be called for primitive types");
@@ -1217,6 +1204,7 @@
   {CC"getInstanceFields",             CC"("HS_RESOLVED_TYPE")["HS_RESOLVED_FIELD,                       FN_PTR(getInstanceFields)},
   {CC"getMethods",                    CC"("HS_RESOLVED_TYPE")["HS_RESOLVED_METHOD,                      FN_PTR(getMethods)},
   {CC"isTypeInitialized",             CC"("HS_RESOLVED_TYPE")Z",                                        FN_PTR(isTypeInitialized)},
+  {CC"isTypeLinked",                  CC"("HS_RESOLVED_TYPE")Z",                                        FN_PTR(isTypeLinked)},
   {CC"hasFinalizableSubclass",        CC"("HS_RESOLVED_TYPE")Z",                                        FN_PTR(hasFinalizableSubclass)},
   {CC"initializeType",                CC"("HS_RESOLVED_TYPE")V",                                        FN_PTR(initializeType)},
   {CC"getMaxCallTargetOffset",        CC"(J)J",                                                         FN_PTR(getMaxCallTargetOffset)},
--- a/src/share/vm/graal/graalVMToCompiler.cpp	Tue Sep 10 16:32:27 2013 -0700
+++ b/src/share/vm/graal/graalVMToCompiler.cpp	Tue Sep 10 16:33:28 2013 -0700
@@ -90,23 +90,33 @@
 }
 
 void VMToCompiler::initOptions() {
-  KlassHandle compilerKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions());
+  KlassHandle optionsKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions());
   Thread* THREAD = Thread::current();
-  compilerKlass->initialize(THREAD);
+  optionsKlass->initialize(THREAD);
   check_pending_exception("Error while calling initOptions");
 }
 
 jboolean VMToCompiler::setOption(Handle option) {
   assert(!option.is_null(), "");
-  KlassHandle compilerKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions());
+  KlassHandle optionsKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions());
 
   Thread* THREAD = Thread::current();
   JavaValue result(T_BOOLEAN);
-  JavaCalls::call_static(&result, compilerKlass, vmSymbols::setOption_name(), vmSymbols::setOption_signature(), option, THREAD);
+  JavaCalls::call_static(&result, optionsKlass, vmSymbols::setOption_name(), vmSymbols::setOption_signature(), option, THREAD);
   check_pending_exception("Error while calling setOption");
   return result.get_jboolean();
 }
 
+void VMToCompiler::finalizeOptions(jboolean ciTime) {
+  KlassHandle optionsKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions());
+  Thread* THREAD = Thread::current();
+  JavaValue result(T_VOID);
+  JavaCallArguments args;
+  args.push_int(ciTime);
+  JavaCalls::call_static(&result, optionsKlass, vmSymbols::finalizeOptions_name(), vmSymbols::bool_void_signature(), &args, THREAD);
+  check_pending_exception("Error while calling finalizeOptions");
+}
+
 void VMToCompiler::compileMethod(Method* method, Handle holder, int entry_bci, jboolean blocking) {
   assert(method != NULL, "just checking");
   assert(!holder.is_null(), "just checking");
--- a/src/share/vm/graal/graalVMToCompiler.hpp	Tue Sep 10 16:32:27 2013 -0700
+++ b/src/share/vm/graal/graalVMToCompiler.hpp	Tue Sep 10 16:33:28 2013 -0700
@@ -57,6 +57,9 @@
   // public static boolean HotSpotOptions.setOption(String option);
   static jboolean setOption(Handle option);
 
+  // public static void HotSpotOptions.finalizeOptions(boolean ciTime);
+  static void finalizeOptions(jboolean ciTime);
+
   // public abstract boolean compileMethod(long vmId, String name, int entry_bci, boolean blocking);
   static void compileMethod(Method* method, Handle holder, int entry_bci, jboolean blocking);
 
--- a/src/share/vm/runtime/gpu.hpp	Tue Sep 10 16:32:27 2013 -0700
+++ b/src/share/vm/runtime/gpu.hpp	Tue Sep 10 16:33:28 2013 -0700
@@ -26,6 +26,9 @@
 #define SHARE_VM_RUNTIME_GPU_HPP
 
 #include "runtime/atomic.hpp"
+#include "oops/symbol.hpp"
+
+class PTXKernelArguments;
 
 // gpu defines the interface to the graphics processor; this includes traditional
 // GPU services such as graphics kernel load and execute.
@@ -43,7 +46,7 @@
   
   static void * generate_kernel(unsigned char *code, int code_len, const char *name);
 
-  static bool execute_kernel(address kernel, JavaCallArguments * jca);
+  static bool execute_kernel(address kernel, PTXKernelArguments & ptxka, JavaValue & ret);
 
   static void set_available(bool value) {
     _available = value;
@@ -80,6 +83,7 @@
 # include "gpu_bsd.hpp"
 #endif
 
+public:
 # include "ptx/vm/gpu_ptx.hpp"
 
 };