changeset 11644:e9fc19eb3efb

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Fri, 13 Sep 2013 23:12:10 +0200
parents 2bd626188d31 (current diff) a0566c8dcabf (diff)
children 2278d53b4d38
files graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitAndNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitBooleanNode.java src/gpu/ptx/vm/kernelArguments.cpp src/gpu/ptx/vm/kernelArguments.hpp
diffstat 282 files changed, 4817 insertions(+), 2473 deletions(-) [+]
line wrap: on
line diff
--- a/README_GRAAL.txt	Thu Sep 05 16:36:40 2013 +0200
+++ b/README_GRAAL.txt	Fri Sep 13 23:12:10 2013 +0200
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DelegatingCodeCacheProvider.java	Fri Sep 13 23:12:10 2013 +0200
@@ -0,0 +1,72 @@
+/*
+ * 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.api.code;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * A {@link CodeCacheProvider} that delegates to another {@link CodeCacheProvider}.
+ */
+public class DelegatingCodeCacheProvider extends DelegatingMetaAccessProvider implements CodeCacheProvider {
+
+    public DelegatingCodeCacheProvider(CodeCacheProvider delegate) {
+        super(delegate);
+    }
+
+    @Override
+    protected CodeCacheProvider delegate() {
+        return (CodeCacheProvider) super.delegate();
+    }
+
+    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) {
+        return delegate().addMethod(method, compResult);
+    }
+
+    public String disassemble(CompilationResult compResult, InstalledCode installedCode) {
+        return delegate().disassemble(compResult, installedCode);
+    }
+
+    public RegisterConfig lookupRegisterConfig() {
+        return delegate().lookupRegisterConfig();
+    }
+
+    public int getMinimumOutgoingSize() {
+        return delegate().getMinimumOutgoingSize();
+    }
+
+    public ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) {
+        return delegate().lookupForeignCall(descriptor);
+    }
+
+    public int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) {
+        return delegate().encodeDeoptActionAndReason(action, reason);
+    }
+
+    public boolean needsDataPatch(Constant constant) {
+        return delegate().needsDataPatch(constant);
+    }
+
+    public TargetDescription getTarget() {
+        return delegate().getTarget();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DelegatingMetaAccessProvider.java	Fri Sep 13 23:12:10 2013 +0200
@@ -0,0 +1,89 @@
+/*
+ * 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.api.meta;
+
+import java.lang.reflect.*;
+
+/**
+ * A {@link MetaAccessProvider} that delegates to another {@link MetaAccessProvider}.
+ */
+public class DelegatingMetaAccessProvider implements MetaAccessProvider {
+
+    private final MetaAccessProvider delegate;
+
+    public DelegatingMetaAccessProvider(MetaAccessProvider delegate) {
+        this.delegate = delegate;
+    }
+
+    protected MetaAccessProvider delegate() {
+        return delegate;
+    }
+
+    public ResolvedJavaType lookupJavaType(Class<?> clazz) {
+        return delegate.lookupJavaType(clazz);
+    }
+
+    public ResolvedJavaMethod lookupJavaMethod(Method reflectionMethod) {
+        return delegate.lookupJavaMethod(reflectionMethod);
+    }
+
+    public ResolvedJavaMethod lookupJavaConstructor(Constructor reflectionConstructor) {
+        return delegate.lookupJavaConstructor(reflectionConstructor);
+    }
+
+    public ResolvedJavaField lookupJavaField(Field reflectionField) {
+        return delegate.lookupJavaField(reflectionField);
+    }
+
+    public ResolvedJavaType lookupJavaType(Constant constant) {
+        return delegate.lookupJavaType(constant);
+    }
+
+    public Signature parseMethodDescriptor(String methodDescriptor) {
+        return delegate.parseMethodDescriptor(methodDescriptor);
+    }
+
+    public boolean constantEquals(Constant x, Constant y) {
+        return delegate.constantEquals(x, y);
+    }
+
+    public int lookupArrayLength(Constant array) {
+        return delegate.lookupArrayLength(array);
+    }
+
+    public Constant readUnsafeConstant(Kind kind, Object base, long displacement, boolean compressible) {
+        return delegate.readUnsafeConstant(kind, base, displacement, compressible);
+    }
+
+    public boolean isReexecutable(ForeignCallDescriptor descriptor) {
+        return delegate.isReexecutable(descriptor);
+    }
+
+    public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) {
+        return delegate.getKilledLocations(descriptor);
+    }
+
+    public boolean canDeoptimize(ForeignCallDescriptor descriptor) {
+        return delegate.canDeoptimize(descriptor);
+    }
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Fri Sep 13 23:12:10 2013 +0200
@@ -112,7 +112,7 @@
     int getModifiers();
 
     /**
-     * Checks whether this type is initialized. If a type is initialized it implies that is was
+     * 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayPTXTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -0,0 +1,117 @@
+/*
+ * 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.compiler.ptx.test;
+
+import java.lang.reflect.Method;
+
+import org.junit.*;
+
+public class ArrayPTXTest extends PTXTestBase {
+
+    @Ignore
+    @Test
+    public void testArray() {
+        compile("testArray1I");
+        compile("testArray1J");
+        compile("testArray1B");
+        compile("testArray1S");
+        compile("testArray1C");
+        compile("testArray1F");
+        compile("testArray1D");
+        compile("testArray1L");
+        compile("testStoreArray1I");
+        compile("testStoreArray1J");
+        compile("testStoreArray1B");
+        compile("testStoreArray1S");
+        compile("testStoreArray1F");
+        compile("testStoreArray1D");
+    }
+
+    public static int testArray1I(int[] array, int i) {
+        return array[i];
+    }
+
+    public static long testArray1J(long[] array, int i) {
+        return array[i];
+    }
+
+    public static byte testArray1B(byte[] array, int i) {
+        return array[i];
+    }
+
+    public static short testArray1S(short[] array, int i) {
+        return array[i];
+    }
+
+    public static char testArray1C(char[] array, int i) {
+        return array[i];
+    }
+
+    public static float testArray1F(float[] array, int i) {
+        return array[i];
+    }
+
+    public static double testArray1D(double[] array, int i) {
+        return array[i];
+    }
+
+    public static Object testArray1L(Object[] array, int i) {
+        return array[i];
+    }
+
+    public static void testStoreArray1I(int[] array, int i, int val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1B(byte[] array, int i, byte val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1S(short[] array, int i, short val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1J(long[] array, int i, long val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1F(float[] array, int i, float val) {
+        array[i] = val;
+    }
+
+    public static void testStoreArray1D(double[] array, int i, double val) {
+        array[i] = val;
+    }
+
+    public static void main(String[] args) {
+        ArrayPTXTest test = new ArrayPTXTest();
+        for (Method m : ArrayPTXTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * 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.compiler.ptx.test;
-
-import java.lang.reflect.Method;
-
-import org.junit.*;
-
-public class ArrayTest extends PTXTestBase {
-
-    @Ignore
-    @Test
-    public void testArray() {
-        compile("testArray1I");
-        compile("testArray1J");
-        compile("testArray1B");
-        compile("testArray1S");
-        compile("testArray1C");
-        compile("testArray1F");
-        compile("testArray1D");
-        compile("testArray1L");
-        compile("testStoreArray1I");
-        compile("testStoreArray1J");
-        compile("testStoreArray1B");
-        compile("testStoreArray1S");
-        compile("testStoreArray1F");
-        compile("testStoreArray1D");
-    }
-
-    public static int testArray1I(int[] array, int i) {
-        return array[i];
-    }
-
-    public static long testArray1J(long[] array, int i) {
-        return array[i];
-    }
-
-    public static byte testArray1B(byte[] array, int i) {
-        return array[i];
-    }
-
-    public static short testArray1S(short[] array, int i) {
-        return array[i];
-    }
-
-    public static char testArray1C(char[] array, int i) {
-        return array[i];
-    }
-
-    public static float testArray1F(float[] array, int i) {
-        return array[i];
-    }
-
-    public static double testArray1D(double[] array, int i) {
-        return array[i];
-    }
-
-    public static Object testArray1L(Object[] array, int i) {
-        return array[i];
-    }
-
-    public static void testStoreArray1I(int[] array, int i, int val) {
-        array[i] = val;
-    }
-
-    public static void testStoreArray1B(byte[] array, int i, byte val) {
-        array[i] = val;
-    }
-
-    public static void testStoreArray1S(short[] array, int i, short val) {
-        array[i] = val;
-    }
-
-    public static void testStoreArray1J(long[] array, int i, long val) {
-        array[i] = val;
-    }
-
-    public static void testStoreArray1F(float[] array, int i, float val) {
-        array[i] = val;
-    }
-
-    public static void testStoreArray1D(double[] array, int i, double val) {
-        array[i] = val;
-    }
-
-    public static void main(String[] args) {
-        ArrayTest test = new ArrayTest();
-        for (Method m : ArrayTest.class.getMethods()) {
-            String name = m.getName();
-            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
-                // CheckStyle: stop system..print check
-                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
-                // CheckStyle: resume system..print check
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -39,35 +39,47 @@
 
     public static int testSwitch1I(int a) {
         switch (a) {
-        case 1:
-            return 2;
-        case 2:
-            return 3;
-        default:
-            return 4;
+            case 1:
+                return 2;
+            case 2:
+                return 3;
+            default:
+                return 4;
         }
     }
 
     public static int testLookupSwitch1I(int a) {
         switch (a) {
-        case 0:  return 1;
-        case 1:  return 2;
-        case 2:  return 3;
-        case 3:  return 1;
-        case 4:  return 2;
-        case 5:  return 3;
-        case 6:  return 1;
-        case 7:  return 2;
-        case 8:  return 3;
-        case 9:  return 1;
-        case 10: return 2;
-        case 11: return 3;
-        default: return -1;
+            case 0:
+                return 1;
+            case 1:
+                return 2;
+            case 2:
+                return 3;
+            case 3:
+                return 1;
+            case 4:
+                return 2;
+            case 5:
+                return 3;
+            case 6:
+                return 1;
+            case 7:
+                return 2;
+            case 8:
+                return 3;
+            case 9:
+                return 1;
+            case 10:
+                return 2;
+            case 11:
+                return 3;
+            default:
+                return -1;
         }
     }
 
-    @SuppressWarnings("unused")
-    private static Object foo = null;
+    @SuppressWarnings("unused") private static Object foo = null;
 
     public static boolean testStatic(Object o) {
         foo = o;
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/FloatPTXTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/FloatPTXTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -37,6 +37,8 @@
         if (r.getTargetCode() == null) {
             printReport("Compilation of testAdd2F FAILED");
         }
+
+        /*
         r = compile("testAdd2D");
         if (r.getTargetCode() == null) {
             printReport("Compilation of testAdd2D FAILED");
@@ -58,6 +60,7 @@
         if (r.getTargetCode() == null) {
             printReport("Compilation of testConstD FAILED");
         }
+        */
     }
 
     public static float testAdd2F(float a, float b) {
@@ -84,6 +87,7 @@
         return 32.0 + a;
     }
 
+    @Ignore
     @Test
     public void testSub() {
         CompilationResult r = compile("testSub2F");
@@ -141,6 +145,7 @@
         return 32.0 - a;
     }
 
+    @Ignore
     @Test
     public void testMul() {
         CompilationResult r = compile("testMul2F");
@@ -198,6 +203,7 @@
         return 32.0 * a;
     }
 
+    @Ignore
     @Test
     public void testDiv() {
         CompilationResult r = compile("testDiv2F");
@@ -255,6 +261,7 @@
         return 32.0 / a;
     }
 
+    @Ignore
     @Test
     public void testNeg() {
         CompilationResult r = compile("testNeg2F");
@@ -276,6 +283,7 @@
         return -a;
     }
 
+    @Ignore
     @Test
     public void testRem() {
         // need linkage to PTX remainder()
@@ -360,9 +368,7 @@
         FloatPTXTest test = new FloatPTXTest();
         for (Method m : FloatPTXTest.class.getMethods()) {
             String name = m.getName();
-            if (m.getAnnotation(Test.class) == null &&
-                    name.startsWith("test") &&
-                    name.startsWith("testRem") == false) {
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test") && name.startsWith("testRem") == false) {
                 // CheckStyle: stop system..print check
                 System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
                 // CheckStyle: resume system..print check
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -26,13 +26,21 @@
 
 import java.lang.reflect.Method;
 
-
 public class IntegerPTXTest extends PTXTestBase {
 
     @Test
     public void testAdd() {
 
-        Integer r4 = (Integer) invoke(compile("testAdd2I"), 18, 24);
+        Integer r4 = (Integer) invoke(compile("testAdd2B"), (byte) 6, (byte) 4);
+        if (r4 == null) {
+            printReport("testAdd2B FAILED");
+        } else if (r4.intValue() == testAdd2B((byte) 6, (byte) 4)) {
+            printReport("testAdd2B PASSED");
+        } else {
+            printReport("testAdd2B FAILED");
+        }
+
+        r4 = (Integer) invoke(compile("testAdd2I"), 18, 24);
         if (r4 == null) {
             printReport("testAdd2I FAILED");
         } else if (r4.intValue() == testAdd2I(18, 24)) {
@@ -50,8 +58,6 @@
             printReport("testAdd2L FAILED");
         }
 
-        //invoke(compile("testAdd2B"), (byte) 6, (byte) 4);
-
         r4 = (Integer) invoke(compile("testAddIConst"), 5);
         if (r4 == null) {
             printReport("testAddIConst FAILED");
@@ -69,7 +75,6 @@
         } else {
             printReport("testAddConstI FAILED");
         }
-
     }
 
     public static int testAdd2I(int a, int b) {
@@ -288,6 +293,7 @@
     public static long testRem2L(long a, long b) {
         return a % b;
     }
+
     @Ignore
     @Test
     public void testIntConversion() {
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/LogicPTXTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/LogicPTXTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -26,7 +26,6 @@
 
 import org.junit.Test;
 
-
 /* PTX ISA 3.1 - 8.7.5 Logic and Shift Instructions */
 public class LogicPTXTest extends PTXTestBase {
 
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Fri Sep 13 23:12:10 2013 +0200
@@ -132,8 +132,6 @@
         // Start emiting body of the PTX kernel.
         codeBuffer.emitString0(") {");
         codeBuffer.emitString("");
-
-        codeBuffer.emitString(".reg .u64" + " %rax;");
     }
 
     // Emit .reg space declarations
@@ -144,6 +142,8 @@
 
         final SortedSet<Integer> signed32 = new TreeSet<>();
         final SortedSet<Integer> signed64 = new TreeSet<>();
+        final SortedSet<Integer> float32 = new TreeSet<>();
+        final SortedSet<Integer> float64 = new TreeSet<>();
 
         ValueProcedure trackRegisterKind = new ValueProcedure() {
 
@@ -159,6 +159,12 @@
                        case Long:
                            signed64.add(regVal.getRegister().encoding());
                            break;
+                       case Float:
+                           float32.add(regVal.getRegister().encoding());
+                           break;
+                       case Double:
+                           float64.add(regVal.getRegister().encoding());
+                           break;
                        default :
                            throw GraalInternalError.shouldNotReachHere("unhandled register type "  + value.toString());
                     }
@@ -179,6 +185,12 @@
         for (Integer i : signed64) {
             codeBuffer.emitString(".reg .s64 %r" + i.intValue() + ";");
         }
+        for (Integer i : float32) {
+            codeBuffer.emitString(".reg .f32 %r" + i.intValue() + ";");
+        }
+        for (Integer i : float64) {
+            codeBuffer.emitString(".reg .f64 %r" + i.intValue() + ";");
+        }
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Fri Sep 13 23:12:10 2013 +0200
@@ -123,7 +123,7 @@
         // Additional argument for return value.
         Value[] params = new Value[argCount + 1];
         for (int i = 0; i < argCount; i++) {
-            params[i] = toParamKind(incomingArguments.getArgument(i));
+            params[i] = incomingArguments.getArgument(i);
         }
         // Add the return value as the last parameter.
         params[argCount] =  incomingArguments.getReturn();
@@ -131,7 +131,6 @@
         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));
         }
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/ConditionTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -45,7 +45,7 @@
                         Constant b = Constant.forInt(i < 100 ? a.asInt() : rand.nextInt());
                         boolean result1 = c1.foldCondition(a, b, null, false);
                         boolean result2 = c2.foldCondition(a, b, null, false);
-                        if (result1 && implies) {
+                        if (result1) {
                             assertTrue(result2);
                         }
                     }
@@ -60,7 +60,7 @@
         for (Condition c1 : Condition.values()) {
             for (Condition c2 : Condition.values()) {
                 Condition join = c1.join(c2);
-                assertTrue(join == c2.join(c1));
+                assertEquals(join, c2.join(c1));
                 if (join != null) {
                     for (int i = 0; i < 1000; i++) {
                         Constant a = Constant.forInt(rand.nextInt());
@@ -70,6 +70,8 @@
                         boolean resultJoin = join.foldCondition(a, b, null, false);
                         if (result1 && result2) {
                             assertTrue(resultJoin);
+                        } else {
+                            assertFalse(resultJoin);
                         }
                     }
                 }
@@ -83,7 +85,7 @@
         for (Condition c1 : Condition.values()) {
             for (Condition c2 : Condition.values()) {
                 Condition meet = c1.meet(c2);
-                assertTrue(meet == c2.meet(c1));
+                assertEquals(meet, c2.meet(c1));
                 if (meet != null) {
                     for (int i = 0; i < 1000; i++) {
                         Constant a = Constant.forInt(rand.nextInt());
@@ -93,6 +95,8 @@
                         boolean resultMeet = meet.foldCondition(a, b, null, false);
                         if (result1 || result2) {
                             assertTrue(resultMeet);
+                        } else {
+                            assertFalse(resultMeet);
                         }
                     }
                 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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,11 +222,43 @@
     @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());
     }
 
+    public static String testInstanceOfCheckCastSnippet(Object e) {
+        if (e instanceof Entry) {
+            return ((Entry) e).name;
+        }
+        return null;
+    }
+
+    @Test
+    public void testInstanceOfCheckCast() {
+        StructuredGraph graph = parse("testInstanceOfCheckCastSnippet");
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
+        new ConditionalEliminationPhase(runtime()).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
+
+        assertEquals(0, graph.getNodes().filter(CheckCastNode.class).count());
+    }
+
+    @Test
+    @Ignore
+    public void testInstanceOfCheckCastLowered() {
+        StructuredGraph graph = parse("testInstanceOfCheckCastSnippet");
+
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
+        PhaseContext context = new PhaseContext(runtime(), null, replacements);
+
+        new LoweringPhase(canonicalizer).apply(graph, context);
+        canonicalizer.apply(graph, context);
+        new ConditionalEliminationPhase(runtime()).apply(graph);
+        canonicalizer.apply(graph, context);
+
+        assertEquals(0, graph.getNodes().filter(GuardNode.class).count());
+    }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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,8 +114,8 @@
             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);
-                Assert.assertEquals(afterCanon, graph.getNodes(CheckCastNode.class).count());
+                new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements));
+                Assert.assertEquals(afterCanon, graph.getNodes().filter(CheckCastNode.class).count());
                 return graph;
             }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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,7 @@
             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);
         }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -74,7 +74,7 @@
         final Method method = getMethod("testMethod");
         final StructuredGraph graph = parseDebug(method);
         int graphLineSPs = 0;
-        for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) {
+        for (InfopointNode ipn : graph.getNodes().filter(InfopointNode.class)) {
             if (ipn.reason == InfopointReason.LINE_NUMBER) {
                 ++graphLineSPs;
             }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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 {
 
@@ -241,12 +242,12 @@
         return (2 - rnd) - 1;
     }
 
-    private <T extends Node & Node.IterableNodeType> void test(String test, String ref) {
+    private <T extends 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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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
@@ -44,7 +45,7 @@
 
     @Test
     public void test1() {
-        test("test1Snippet", CheckCastNode.class);
+        testHelper("test1Snippet", CheckCastNode.class);
     }
 
     public static int test1Snippet(Object a) {
@@ -56,7 +57,7 @@
 
     @Test
     public void test2() {
-        test("test2Snippet", CheckCastNode.class);
+        testHelper("test2Snippet", CheckCastNode.class);
     }
 
     public static int test2Snippet(Object a) {
@@ -161,7 +162,7 @@
 
     @Test
     public void test6() {
-        test("test6Snippet", CheckCastNode.class);
+        testHelper("test6Snippet", CheckCastNode.class);
     }
 
     public static int test6Snippet(int i) throws IOException {
@@ -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);
     }
 
@@ -236,14 +237,14 @@
         }
     }
 
-    private <T extends Node & Node.IterableNodeType> void test(String snippet, Class<T> clazz) {
+    private <T extends Node> void testHelper(String snippet, Class<T> clazz) {
         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());
+        Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext());
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -234,17 +234,18 @@
 
                 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) {
                     Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant());
                     Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant());
                 }
-                int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewArrayNode.class).count() + graph.getNodes(CommitAllocationNode.class).count();
+                int newInstanceCount = graph.getNodes().filter(NewInstanceNode.class).count() + graph.getNodes().filter(NewArrayNode.class).count() +
+                                graph.getNodes(CommitAllocationNode.class).count();
                 Assert.assertEquals(0, newInstanceCount);
                 return returnNode;
             }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -167,8 +167,8 @@
     final void testMaterialize(final String snippet, double expectedProbability, int expectedCount, Class<? extends Node>... invalidNodeClasses) {
         StructuredGraph result = processMethod(snippet);
         try {
-            Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes(NewInstanceNode.class).isEmpty());
-            Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes(NewArrayNode.class).isEmpty());
+            Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes().filter(NewInstanceNode.class).isEmpty());
+            Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes().filter(NewArrayNode.class).isEmpty());
 
             NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(result).apply();
             double probabilitySum = 0;
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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);
@@ -279,7 +279,7 @@
     private static int[] countMethodInfopoints(StructuredGraph graph) {
         int start = 0;
         int end = 0;
-        for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) {
+        for (InfopointNode ipn : graph.getNodes().filter(InfopointNode.class)) {
             if (ipn.reason == InfopointReason.METHOD_START) {
                 ++start;
             } else if (ipn.reason == InfopointReason.METHOD_END) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Fri Sep 13 23:12:10 2013 +0200
@@ -36,8 +36,6 @@
 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 = "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 = "Pattern for scope(s) to in which metering is enabled (see DebugFilter and Debug.metric)")
@@ -53,7 +51,7 @@
                    "Partial - aggregate by partially qualified name (e.g., A.B.C.D.Counter and X.Y.Z.D.Counter will be merged to D.Counter)%n" +
                    "Complete - aggregate by qualified name%n" +
                    "Thread - aggregate by qualified name and thread")
-    public static final OptionValue<String> DebugValueSummary = new OptionValue<>("Complete");
+    public static final OptionValue<String> DebugValueSummary = new OptionValue<>("Name");
     @Option(help = "Send Graal IR to dump handlers on error")
     public static final OptionValue<Boolean> DumpOnError = new OptionValue<>(false);
     @Option(help = "Enable expensive assertions")
@@ -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;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Fri Sep 13 23:12:10 2013 +0200
@@ -22,24 +22,49 @@
  */
 package com.oracle.graal.debug;
 
-import com.oracle.graal.debug.internal.*;
+import static com.oracle.graal.debug.Debug.Initialization.*;
 
 import java.io.*;
 import java.util.*;
 import java.util.concurrent.*;
 
+import com.oracle.graal.debug.internal.*;
+
+/**
+ * Scope based debugging facility. This facility is {@link #isEnabled()} if assertions are enabled
+ * for the {@link Debug} class or the {@value Initialization#INITIALIZER_PROPERTY_NAME} system
+ * property is {@code "true"} when {@link Debug} is initialized.
+ */
 public class Debug {
 
-    private static boolean ENABLED = false;
+    /**
+     * Class to assist with initialization of {@link Debug}.
+     */
+    public static class Initialization {
+
+        public static final String INITIALIZER_PROPERTY_NAME = "graal.debug.enable";
 
-    public static void enable() {
-        ENABLED = true;
+        private static boolean initialized;
+
+        /**
+         * Determines if {@link Debug} has been initialized.
+         */
+        public static boolean isDebugInitialized() {
+            return initialized;
+        }
+
     }
 
-    public static void disable() {
-        ENABLED = false;
+    @SuppressWarnings("all")
+    private static boolean initialize() {
+        boolean assertionsEnabled = false;
+        assert assertionsEnabled = true;
+        Initialization.initialized = true;
+        return assertionsEnabled || Boolean.getBoolean(INITIALIZER_PROPERTY_NAME);
     }
 
+    private static final boolean ENABLED = initialize();
+
     public static boolean isEnabled() {
         return ENABLED;
     }
@@ -330,7 +355,7 @@
 
     public static DebugMetric metric(String name) {
         if (ENABLED) {
-            return new MetricImpl(name);
+            return new MetricImpl(name, true);
         } else {
             return VOID_METRIC;
         }
@@ -342,6 +367,9 @@
         }
     }
 
+    /**
+     * Creates an object for counting value frequencies.
+     */
     public static DebugHistogram createHistogram(String name) {
         return new DebugHistogramImpl(name);
     }
@@ -402,11 +430,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 +453,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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugMetric.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugTimer.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Fri Sep 13 23:12:10 2013 +0200
@@ -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/DebugScope.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Fri Sep 13 23:12:10 2013 +0200
@@ -92,7 +92,6 @@
     private static ThreadLocal<DebugScope> instanceTL = new ThreadLocal<>();
     private static ThreadLocal<DebugConfig> configTL = new ThreadLocal<>();
     private static ThreadLocal<Throwable> lastExceptionThrownTL = new ThreadLocal<>();
-    private static DebugTimer scopeTime = Debug.timer("ScopeTime");
 
     private final DebugScope parent;
     private IndentImpl lastUsedIndent;
@@ -239,7 +238,7 @@
         }
         instanceTL.set(newChild);
         newChild.updateFlags();
-        try (TimerCloseable a = scopeTime.start()) {
+        try {
             return executeScope(runnable, callable);
         } finally {
             newChild.context = null;
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugValue.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugValue.java	Fri Sep 13 23:12:10 2013 +0200
@@ -30,10 +30,12 @@
 
     private final String name;
     private int index;
+    private boolean conditional;
 
-    protected DebugValue(String name) {
+    protected DebugValue(String name, boolean conditional) {
         this.name = name;
         this.index = -1;
+        this.conditional = conditional;
     }
 
     protected long getCurrentValue() {
@@ -46,6 +48,14 @@
         DebugScope.getInstance().setCurrentValue(index, l);
     }
 
+    public void setConditional(boolean flag) {
+        conditional = flag;
+    }
+
+    public boolean isConditional() {
+        return conditional;
+    }
+
     private void ensureInitialized() {
         if (index == -1) {
             index = KeyRegistry.register(this);
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MetricImpl.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MetricImpl.java	Fri Sep 13 23:12:10 2013 +0200
@@ -26,8 +26,8 @@
 
 public final class MetricImpl extends DebugValue implements DebugMetric {
 
-    public MetricImpl(String name) {
-        super(name);
+    public MetricImpl(String name, boolean conditional) {
+        super(name, conditional);
     }
 
     public void increment() {
@@ -35,7 +35,7 @@
     }
 
     public void add(long value) {
-        if (Debug.isMeterEnabled()) {
+        if (!isConditional() || Debug.isMeterEnabled()) {
             super.addToCurrentValue(value);
         }
     }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerCloseable.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerCloseable.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerImpl.java	Fri Sep 13 23:12:10 2013 +0200
@@ -37,59 +37,78 @@
         }
     };
 
-    private ThreadLocal<Long> valueToSubstract = new ThreadLocal<>();
+    /**
+     * Records the most recent active timer.
+     */
+    private static ThreadLocal<AbstractTimer> currentTimer = new ThreadLocal<>();
+
+    private final DebugValue flat;
 
-    public TimerImpl(String name) {
-        super(name);
+    public TimerImpl(String name, boolean conditional) {
+        super(name + "_Accm", conditional);
+        this.flat = new DebugValue(name + "_Flat", conditional) {
+
+            @Override
+            public String toString(long value) {
+                return valueToString(value);
+            }
+        };
     }
 
     @Override
     public TimerCloseable start() {
-        if (Debug.isTimeEnabled()) {
+        if (!isConditional() || Debug.isTimeEnabled()) {
             long startTime;
             if (threadMXBean.isCurrentThreadCpuTimeSupported()) {
                 startTime = threadMXBean.getCurrentThreadCpuTime();
             } else {
                 startTime = System.nanoTime();
             }
-            if (valueToSubstract.get() == null) {
-                valueToSubstract.set(0L);
-            }
-            long previousValueToSubstract = valueToSubstract.get();
+
             AbstractTimer result;
             if (threadMXBean.isCurrentThreadCpuTimeSupported()) {
-                result = new CpuTimeTimer(startTime, previousValueToSubstract);
+                result = new CpuTimeTimer(startTime);
             } else {
-                result = new SystemNanosTimer(startTime, previousValueToSubstract);
+                result = new SystemNanosTimer(startTime);
             }
-            valueToSubstract.set(0L);
+            currentTimer.set(result);
             return result;
         } else {
             return VOID_CLOSEABLE;
         }
     }
 
+    public static String valueToString(long value) {
+        return String.format("%d.%d ms", value / 1000000, (value / 100000) % 10);
+    }
+
     @Override
     public String toString(long value) {
-        return String.format("%d.%d ms", value / 1000000, (value / 100000) % 10);
+        return valueToString(value);
     }
 
     private abstract class AbstractTimer implements TimerCloseable {
 
+        private final AbstractTimer parent;
         private final long startTime;
-        private final long previousValueToSubstract;
+        private long nestedTimeToSubtract;
 
-        private AbstractTimer(long startTime, long previousValueToSubstract) {
+        private AbstractTimer(long startTime) {
+            this.parent = currentTimer.get();
             this.startTime = startTime;
-            this.previousValueToSubstract = previousValueToSubstract;
         }
 
         @Override
         public void close() {
-            long timeSpan = currentTime() - startTime;
-            long oldValueToSubstract = valueToSubstract.get();
-            valueToSubstract.set(timeSpan + previousValueToSubstract);
-            TimerImpl.this.addToCurrentValue(timeSpan - oldValueToSubstract);
+            long endTime = currentTime();
+            long timeSpan = endTime - startTime;
+            if (parent != null) {
+                parent.nestedTimeToSubtract += timeSpan;
+            }
+            currentTimer.set(parent);
+            long flatTime = timeSpan - nestedTimeToSubtract;
+            TimerImpl.this.addToCurrentValue(timeSpan);
+            flat.addToCurrentValue(flatTime);
         }
 
         protected abstract long currentTime();
@@ -97,8 +116,8 @@
 
     private final class SystemNanosTimer extends AbstractTimer {
 
-        public SystemNanosTimer(long startTime, long previousValueToSubstract) {
-            super(startTime, previousValueToSubstract);
+        public SystemNanosTimer(long startTime) {
+            super(startTime);
         }
 
         @Override
@@ -109,8 +128,8 @@
 
     private final class CpuTimeTimer extends AbstractTimer {
 
-        public CpuTimeTimer(long startTime, long previousValueToSubstract) {
-            super(startTime, previousValueToSubstract);
+        public CpuTimeTimer(long startTime) {
+            super(startTime);
         }
 
         @Override
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -32,7 +32,7 @@
 
 public class TypedNodeIteratorTest {
 
-    private static class TestNode extends Node implements Node.IterableNodeType, TestNodeInterface {
+    private static class TestNode extends Node implements IterableNodeType, TestNodeInterface {
 
         private final String name;
 
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java	Fri Sep 13 23:12:10 2013 +0200
@@ -43,7 +43,7 @@
         }
     }
 
-    private static class NodeB extends NodeA implements Node.IterableNodeType {
+    private static class NodeB extends NodeA implements IterableNodeType {
 
         public NodeB(String name) {
             super(name);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.*;
 
@@ -125,37 +124,49 @@
         }
     }
 
+    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) {
-        if (node.id >= 0 && node.id < nodeModCounts.length) {
-            return nodeModCounts[node.id];
+        int id = extractOriginalNodeId(node);
+        if (id >= 0 && id < nodeModCounts.length) {
+            return nodeModCounts[id];
         }
         return 0;
     }
 
     void incModCount(Node node) {
-        if (node.id >= 0) {
-            if (node.id >= nodeModCounts.length) {
-                nodeModCounts = Arrays.copyOf(nodeModCounts, node.id + 30);
+        int id = extractOriginalNodeId(node);
+        if (id >= 0) {
+            if (id >= nodeModCounts.length) {
+                nodeModCounts = Arrays.copyOf(nodeModCounts, id + 30);
             }
-            nodeModCounts[node.id]++;
+            nodeModCounts[id]++;
         } else {
             assert false;
         }
     }
 
     int usageModCount(Node node) {
-        if (node.id >= 0 && node.id < nodeUsageModCounts.length) {
-            return nodeUsageModCounts[node.id];
+        int id = extractOriginalNodeId(node);
+        if (id >= 0 && id < nodeUsageModCounts.length) {
+            return nodeUsageModCounts[id];
         }
         return 0;
     }
 
     void incUsageModCount(Node node) {
-        if (node.id >= 0) {
-            if (node.id >= nodeUsageModCounts.length) {
-                nodeUsageModCounts = Arrays.copyOf(nodeUsageModCounts, node.id + 30);
+        int id = extractOriginalNodeId(node);
+        if (id >= 0) {
+            if (id >= nodeUsageModCounts.length) {
+                nodeUsageModCounts = Arrays.copyOf(nodeUsageModCounts, id + 30);
             }
-            nodeUsageModCounts[node.id]++;
+            nodeUsageModCounts[id]++;
         } else {
             assert false;
         }
@@ -506,7 +517,7 @@
      * {@code type}.
      * 
      * @param type the type of node to return
-     * @return an {@link Iterable} providing all the matching nodes.
+     * @return an {@link Iterable} providing all the matching nodes
      */
     public <T extends Node & IterableNodeType> NodeIterable<T> getNodes(final Class<T> type) {
         final NodeClass nodeClass = NodeClass.get(type);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/IterableNodeType.java	Fri Sep 13 23:12:10 2013 +0200
@@ -0,0 +1,32 @@
+/*
+ * 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.graph;
+
+/**
+ * A marker for a node type supporting {@linkplain Graph#getNodes(Class) fast iteration} of its
+ * instances in a graph. The support for fast iteration comes with a memory cost (e.g., extra data
+ * structures {@link Graph}) so only node types for which fast iteration provides a compilation
+ * performance benefit should implement this interface.
+ */
+public interface IterableNodeType {
+}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Fri Sep 13 23:12:10 2013 +0200
@@ -111,9 +111,6 @@
     public interface ValueNumberable {
     }
 
-    public interface IterableNodeType {
-    }
-
     private Graph graph;
     int id;
 
@@ -236,11 +233,7 @@
             if (usage1 == null) {
                 return 1;
             }
-            int count = 2;
-            for (int i = 0; i < extraUsages.length && extraUsages[i] != null; i++) {
-                count++;
-            }
-            return count;
+            return 2 + indexOfLastNonNull(extraUsages) + 1;
         }
     }
 
@@ -252,6 +245,40 @@
     }
 
     /**
+     * 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
@@ -264,37 +291,23 @@
             usage1 = node;
         } else {
             int length = extraUsages.length;
-            int start = extraUsages.length >> 1;
-            if (start < length && extraUsages[start] == null) {
-                start = 0;
-            }
-            for (int i = start; i < length; i++) {
-                if (extraUsages[i] == null) {
-                    extraUsages[i] = node;
-                    return;
+            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;
                 }
             }
-            extraUsages = Arrays.copyOf(extraUsages, length * 2 + 1);
-            extraUsages[length] = node;
         }
     }
 
-    private Node removeFirstExtraUsage() {
-        Node res = null;
-        if (extraUsages.length > 0) {
-            res = extraUsages[0];
-            for (int i = 1; i < extraUsages.length; ++i) {
-                Node n = extraUsages[i];
-                extraUsages[i - 1] = n;
-                if (n == null) {
-                    break;
-                }
-            }
-            extraUsages[extraUsages.length - 1] = null;
-        }
-        return res;
-    }
-
     /**
      * Removes a given node from this node's {@linkplain #usages() usages}.
      * 
@@ -305,36 +318,47 @@
         // 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 == null) {
-            return false;
-        }
         if (usage0 == node) {
-            usage0 = usage1;
             if (usage1 != null) {
-                usage1 = removeFirstExtraUsage();
+                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 == null) {
-            return false;
-        }
         if (usage1 == node) {
-            usage1 = removeFirstExtraUsage();
+            int lastNonNull = indexOfLastNonNull(extraUsages);
+            if (lastNonNull >= 0) {
+                usage1 = extraUsages[lastNonNull];
+                extraUsages[lastNonNull] = null;
+            } else {
+                // usage1 is the last element
+                usage1 = null;
+            }
             return true;
         }
-        int length = extraUsages.length;
-        for (int i = 0; i < length; i++) {
-            if (extraUsages[i] == node) {
-                for (int j = i + 1; j < length; j++) {
-                    Node toMove = extraUsages[j];
-                    extraUsages[j - 1] = toMove;
-                    if (toMove == null) {
-                        break;
+        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;
                 }
-                extraUsages[length - 1] = null;
-
-                return true;
             }
         }
         return false;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Fri Sep 13 23:12:10 2013 +0200
@@ -31,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;
 
@@ -185,14 +184,14 @@
         }
         this.nameTemplate = newNameTemplate == null ? newShortName : newNameTemplate;
         this.shortName = newShortName;
-        if (Node.IterableNodeType.class.isAssignableFrom(clazz)) {
+        if (IterableNodeType.class.isAssignableFrom(clazz)) {
             this.iterableId = nextIterableId++;
             List<NodeClass> existingClasses = new LinkedList<>();
             for (FieldIntrospection nodeClass : allClasses.values()) {
                 if (clazz.isAssignableFrom(nodeClass.clazz)) {
                     existingClasses.add((NodeClass) nodeClass);
                 }
-                if (nodeClass.clazz.isAssignableFrom(clazz) && Node.IterableNodeType.class.isAssignableFrom(nodeClass.clazz)) {
+                if (nodeClass.clazz.isAssignableFrom(clazz) && IterableNodeType.class.isAssignableFrom(nodeClass.clazz)) {
                     NodeClass superNodeClass = (NodeClass) nodeClass;
                     superNodeClass.iterableIds = Arrays.copyOf(superNodeClass.iterableIds, superNodeClass.iterableIds.length + 1);
                     superNodeClass.iterableIds[superNodeClass.iterableIds.length - 1] = this.iterableId;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Sep 13 23:12:10 2013 +0200
@@ -46,7 +46,6 @@
 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;
@@ -162,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);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Fri Sep 13 23:12:10 2013 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.ptx;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * HotSpot PTX specific backend.
+ */
+public class PTXHotSpotBackend extends HotSpotBackend {
+
+    public PTXHotSpotBackend(HotSpotRuntime runtime, TargetDescription target) {
+        super(runtime, target);
+    }
+
+    @Override
+    public FrameMap newFrameMap() {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod installedCodeOwner) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    protected AbstractAssembler createAssembler(FrameMap frameMap) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, CallingConvention cc, LIR lir) {
+        throw new InternalError("NYI");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotGraalRuntime.java	Fri Sep 13 23:12:10 2013 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.ptx;
+
+import com.oracle.graal.ptx.*;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+
+/**
+ * PTX specific implementation of {@link HotSpotGraalRuntime}.
+ */
+public class PTXHotSpotGraalRuntime extends HotSpotGraalRuntime {
+
+    protected PTXHotSpotGraalRuntime() {
+    }
+
+    /**
+     * Called from C++ code to retrieve the singleton instance, creating it first if necessary.
+     */
+    public static HotSpotGraalRuntime makeInstance() {
+        HotSpotGraalRuntime graalRuntime = graalRuntime();
+        if (graalRuntime == null) {
+            HotSpotGraalRuntimeFactory factory = findFactory("PTX");
+            if (factory != null) {
+                graalRuntime = factory.createRuntime();
+            } else {
+                graalRuntime = new PTXHotSpotGraalRuntime();
+            }
+            graalRuntime.completeInitialization();
+        }
+        return graalRuntime;
+    }
+
+    protected Architecture createArchitecture() {
+        return new PTX();
+    }
+
+    @Override
+    protected TargetDescription createTarget() {
+        final int stackFrameAlignment = 16;
+        final int implicitNullCheckLimit = 4096;
+        final boolean inlineObjects = true;
+        return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+    }
+
+    @Override
+    protected HotSpotBackend createBackend() {
+        return new PTXHotSpotBackend(getRuntime(), getTarget());
+    }
+
+    @Override
+    protected HotSpotRuntime createRuntime() {
+        return new PTXHotSpotRuntime(config, this);
+    }
+
+    @Override
+    protected Value[] getNativeABICallerSaveRegisters() {
+        throw new InternalError("NYI");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java	Fri Sep 13 23:12:10 2013 +0200
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.ptx;
+
+import static com.oracle.graal.ptx.PTX.*;
+
+import java.util.*;
+
+import com.oracle.graal.ptx.*;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+
+public class PTXHotSpotRegisterConfig implements RegisterConfig {
+
+    private final Architecture architecture;
+
+    private final Register[] allocatable;
+
+    private final HashMap<PlatformKind, Register[]> categorized = new HashMap<>();
+
+    private final RegisterAttributes[] attributesMap;
+
+    @Override
+    public Register[] getAllocatableRegisters() {
+        return allocatable.clone();
+    }
+
+    public Register[] getAllocatableRegisters(PlatformKind kind) {
+        if (categorized.containsKey(kind)) {
+            return categorized.get(kind);
+        }
+
+        ArrayList<Register> list = new ArrayList<>();
+        for (Register reg : getAllocatableRegisters()) {
+            if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) {
+                list.add(reg);
+            }
+        }
+
+        Register[] ret = list.toArray(new Register[0]);
+        categorized.put(kind, ret);
+        return ret;
+    }
+
+    @Override
+    public RegisterAttributes[] getAttributesMap() {
+        return attributesMap.clone();
+    }
+
+    private final Register[] javaGeneralParameterRegisters;
+    private final Register[] nativeGeneralParameterRegisters;
+
+    private static Register[] initAllocatable() {
+        Register[] registers = new Register[] {
+            param0, param1, param2, param3,
+            param4, param5, param6, param7,
+            r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
+            r8,  r9,  r10, r11, r12, r13, r14, r15,
+            retReg,
+        };
+
+        return registers;
+    }
+
+    public PTXHotSpotRegisterConfig(Architecture architecture) {
+        this.architecture = architecture;
+
+        javaGeneralParameterRegisters = paramRegisters;
+        nativeGeneralParameterRegisters = gprRegisters;
+
+        allocatable = initAllocatable();
+        attributesMap = RegisterAttributes.createMap(this, PTX.allRegisters);
+    }
+
+    @Override
+    public Register[] getCallerSaveRegisters() {
+        // No caller save registers; return empty array
+        return new Register[]{};
+    }
+
+    @Override
+    public Register getRegisterForRole(int index) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) {
+        if (type == Type.NativeCall) {
+            return callingConvention(nativeGeneralParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
+        }
+        return callingConvention(javaGeneralParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
+    }
+
+    public Register[] getCallingConventionRegisters(Type type, Kind kind) {
+        assert architecture.canStoreValue(REG, kind);
+        return type == Type.NativeCall ? nativeGeneralParameterRegisters : javaGeneralParameterRegisters;
+    }
+
+    private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) {
+        AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
+
+        int currentGeneral = 0;
+        int currentStackOffset = 0;
+
+        for (int i = 0; i < parameterTypes.length; i++) {
+            final Kind kind = parameterTypes[i].getKind();
+
+            switch (kind) {
+                case Byte:
+                case Boolean:
+                case Short:
+                case Char:
+                case Int:
+                case Long:
+                case Float:
+                case Double:
+                case Object:
+                    if (!stackOnly && currentGeneral < generalParameterRegisters.length) {
+                        Register register = generalParameterRegisters[currentGeneral++];
+                        locations[i] = register.asValue(kind);
+                    }
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+
+            if (locations[i] == null) {
+                locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out);
+                currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize);
+            }
+        }
+
+        Kind returnKind = returnType == null ? Kind.Void : returnType.getKind();
+        AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(returnKind);
+        return new CallingConvention(currentStackOffset, returnLocation, locations);
+    }
+
+    @Override
+    public Register getReturnRegister(Kind kind) {
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+            case Long:
+            case Object:
+            case Float:
+            case Double:
+                return retReg;
+            case Void:
+            case Illegal:
+                return null;
+            default:
+                throw new UnsupportedOperationException("no return register for type " + kind);
+        }
+    }
+
+    @Override
+    public Register getFrameRegister() {
+        // No frame register
+        return null;
+    }
+
+    public CalleeSaveLayout getCalleeSaveLayout() {
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + "CallerSave:  " + Arrays.toString(getCallerSaveRegisters()) + "%n");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRuntime.java	Fri Sep 13 23:12:10 2013 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.ptx;
+
+import static com.oracle.graal.ptx.PTX.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.spi.*;
+
+public class PTXHotSpotRuntime extends HotSpotRuntime {
+
+    public PTXHotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) {
+        super(config, graalRuntime);
+
+    }
+
+    @Override
+    public void registerReplacements(Replacements replacements) {
+        //TODO: Do we need to implement this functionality for PTX?
+    }
+
+    // PTX code does not use stack or stack pointer
+    @Override
+    public Register stackPointerRegister() {
+        return Register.None;
+    }
+
+    // PTX code does not have heap register
+    @Override
+    public Register heapBaseRegister() {
+        return Register.None;
+    }
+
+    // Thread register is %tid.
+    @Override
+    public Register threadRegister() {
+        return tid;
+    }
+
+    @Override
+    protected RegisterConfig createRegisterConfig() {
+        return new PTXHotSpotRegisterConfig(graalRuntime.getTarget().arch);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/CompilerThread.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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,19 @@
     }
 
     /**
+     * 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) {
+            assert !Debug.Initialization.isDebugInitialized();
+            System.setProperty(Debug.Initialization.INITIALIZER_PROPERTY_NAME, "true");
+        }
+    }
+
+    /**
      * 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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/VMToCompilerImpl.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/HotSpotRuntime.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.*;
@@ -637,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.GuardsStage.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);
@@ -676,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.GuardsStage.FIXED_DEOPTS) {
                 CommitAllocationNode commit = (CommitAllocationNode) n;
 
                 ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()];
@@ -759,7 +752,7 @@
                 graph.removeFixed(commit);
             }
         } else if (n instanceof OSRStartNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
                 OSRStartNode osrStart = (OSRStartNode) n;
                 StartNode newStart = graph.add(new StartNode());
                 LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind())));
@@ -788,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.GuardsStage.FIXED_DEOPTS) {
                 instanceofSnippets.lower((InstanceOfNode) n, tool);
             }
         } else if (n instanceof InstanceOfDynamicNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
                 instanceofSnippets.lower((InstanceOfDynamicNode) n, tool);
             }
         } else if (n instanceof NewInstanceNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_FSA) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsStage.AFTER_FSA) {
                 newObjectSnippets.lower((NewInstanceNode) n);
             }
         } else if (n instanceof NewArrayNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_FSA) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsStage.AFTER_FSA) {
                 newObjectSnippets.lower((NewArrayNode) n);
             }
         } else if (n instanceof DynamicNewArrayNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_FSA) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsStage.AFTER_FSA) {
                 newObjectSnippets.lower((DynamicNewArrayNode) n);
             }
         } else if (n instanceof MonitorEnterNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
                 monitorSnippets.lower((MonitorEnterNode) n, tool);
             }
         } else if (n instanceof MonitorExitNode) {
-            if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) {
+            if (graph.getGuardsPhase() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
                 monitorSnippets.lower((MonitorExitNode) n, tool);
             }
         } else if (n instanceof G1PreWriteBarrier) {
@@ -830,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.GuardsStage.AFTER_FSA) {
                 newObjectSnippets.lower((NewMultiArrayNode) n);
             }
         } else if (n instanceof LoadExceptionObjectNode) {
@@ -850,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.GuardsStage.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()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/VerifyHotSpotOptionsPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -26,7 +26,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.Node.IterableNodeType;
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -37,7 +36,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, Lowerable {
 
     public ArrayCopyNode(Invoke invoke) {
         super(invoke);
@@ -87,7 +86,7 @@
         // 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);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/ReflectionGetCallerClassNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.GuardsStage.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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -112,7 +112,7 @@
      * jump. When the block is seen the second time, a MergeNode is created to correctly merge the
      * now two different predecessor states.
      */
-    private static class BlockPlaceholderNode extends FixedWithNextNode implements Node.IterableNodeType {
+    private static class BlockPlaceholderNode extends FixedWithNextNode implements IterableNodeType {
 
         public BlockPlaceholderNode() {
             super(StampFactory.forVoid());
@@ -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/AMD64FrameMap.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java	Fri Sep 13 23:12:10 2013 +0200
@@ -28,12 +28,12 @@
 
 /**
  * AMD64 specific frame map.
- * 
+ *
  * This is the format of an AMD64 stack frame:
- * 
+ *
  * <pre>
  *   Base       Contents
- * 
+ *
  *            :                                :  -----
  *   caller   | incoming overflow argument n   |    ^
  *   frame    :     ...                        :    | positive
@@ -55,9 +55,9 @@
  *            :     ...                        :    | positive   |      |
  *            | outgoing overflow argument 0   |    | offsets    v      v
  *    %sp-->  +--------------------------------+---------------------------
- * 
+ *
  * </pre>
- * 
+ *
  * The spill slot area also includes stack allocated memory blocks (ALLOCA blocks). The size of such
  * a block may be greater than the size of a normal spill slot or the word size.
  * <p>
@@ -67,7 +67,7 @@
  * call-free methods also have this space reserved. Then the VM can use the memory at offset 0
  * relative to the stack pointer.
  */
-public final class AMD64FrameMap extends FrameMap {
+public class AMD64FrameMap extends FrameMap {
 
     public AMD64FrameMap(CodeCacheProvider runtime, TargetDescription target, RegisterConfig registerConfig) {
         super(runtime, target, registerConfig);
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMemOp.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMemOp.java	Fri Sep 13 23:12:10 2013 +0200
@@ -208,6 +208,12 @@
                 case Long:
                     masm.ld_return_address("u64", asRegister(result), addr.getBase(), addr.getDisplacement());
                     break;
+                case Float:
+                    masm.ld_return_address("f32", asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Double:
+                    masm.ld_return_address("f64", asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
             }
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXParameterOp.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXParameterOp.java	Fri Sep 13 23:12:10 2013 +0200
@@ -48,6 +48,9 @@
         for (int i = 0; i < argCount; i++) {
             Kind paramKind = params[i].getKind();
             switch (paramKind) {
+            case Byte :
+                masm.param_8_decl(asRegister(params[i]), (i == (argCount - 1)));
+                break;
             case Int :
                 masm.param_32_decl(asIntReg(params[i]), (i == (argCount - 1)));
                 break;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Fri Sep 13 23:12:10 2013 +0200
@@ -116,7 +116,7 @@
     /**
      * Gets the frame size of the compiled frame, not including the size of the
      * {@link Architecture#getReturnAddressSize() return address slot}.
-     * 
+     *
      * @return The size of the frame (in bytes).
      */
     public int frameSize() {
@@ -136,7 +136,7 @@
     /**
      * Gets the total frame size of the compiled frame, including the size of the
      * {@link Architecture#getReturnAddressSize() return address slot}.
-     * 
+     *
      * @return The total size of the frame (in bytes).
      */
     public abstract int totalFrameSize();
@@ -149,7 +149,7 @@
 
     /**
      * Aligns the given frame size to the stack alignment size and return the aligned size.
-     * 
+     *
      * @param size the initial frame size to be aligned
      * @return the aligned frame size
      */
@@ -181,7 +181,7 @@
 
     /**
      * Computes the offset of a stack slot relative to the frame register.
-     * 
+     *
      * @param slot a stack slot
      * @return the offset of the stack slot
      */
@@ -197,7 +197,7 @@
     /**
      * Computes the index of a stack slot relative to slot 0. This is also the bit index of stack
      * slots in the reference map.
-     * 
+     *
      * @param slot a stack slot
      * @return the index of the stack slot
      */
@@ -209,7 +209,7 @@
     /**
      * Gets the offset from the stack pointer to the stack area where callee-saved registers are
      * stored.
-     * 
+     *
      * @return The offset to the callee save area (in bytes).
      */
     public abstract int offsetToCalleeSaveArea();
@@ -217,7 +217,7 @@
     /**
      * Informs the frame map that the compiled code calls a particular method, which may need stack
      * space for outgoing arguments.
-     * 
+     *
      * @param cc The calling convention for the called method.
      */
     public void callsMethod(CallingConvention cc) {
@@ -226,7 +226,7 @@
 
     /**
      * Reserves space for stack-based outgoing arguments.
-     * 
+     *
      * @param argsSize The amount of space (in bytes) to reserve for stack-based outgoing arguments.
      */
     public void reserveOutgoing(int argsSize) {
@@ -239,7 +239,7 @@
      * Reserves a new spill slot in the frame of the method being compiled. The returned slot is
      * aligned on its natural alignment, i.e., an 8-byte spill slot is aligned at an 8-byte
      * boundary.
-     * 
+     *
      * @param kind The kind of the spill slot to be reserved.
      * @param additionalOffset
      * @return A spill slot denoting the reserved memory area.
@@ -247,9 +247,20 @@
     protected abstract StackSlot allocateNewSpillSlot(PlatformKind kind, int additionalOffset);
 
     /**
+     * Returns the spill slot size for the given {@link PlatformKind}.
+     * The default value is the size in bytes for the target architecture.
+     * @param kind the {@link PlatformKind} to be stored in the spill slot.
+     * @return the size in bytes
+     */
+    protected int spillSlotSize(PlatformKind kind) {
+        return target.arch.getSizeInBytes(kind);
+    }
+
+    /**
      * Reserves a spill slot in the frame of the method being compiled. The returned slot is aligned
-     * on its natural alignment, i.e., an 8-byte spill slot is aligned at an 8-byte boundary.
-     * 
+     * on its natural alignment, i.e., an 8-byte spill slot is aligned at an 8-byte boundary,
+     * unless overridden by a subclass.
+     *
      * @param kind The kind of the spill slot to be reserved.
      * @return A spill slot denoting the reserved memory area.
      */
@@ -267,7 +278,7 @@
                 }
             }
         }
-        int size = target.arch.getSizeInBytes(kind);
+        int size = spillSlotSize(kind);
         spillSize = NumUtil.roundUp(spillSize + size, size);
         return allocateNewSpillSlot(kind, 0);
     }
@@ -288,7 +299,7 @@
     /**
      * Reserves a block of memory in the frame of the method being compiled. The returned block is
      * aligned on a word boundary. If the requested size is 0, the method returns {@code null}.
-     * 
+     *
      * @param size The size to reserve (in bytes).
      * @param refs Specifies if the block is all references. If true, the block will be in all
      *            reference maps for this method. The caller is responsible to initialize the memory
@@ -340,7 +351,7 @@
      * Marks the specified location as a reference in the reference map of the debug information.
      * The tracked location can be a {@link RegisterValue} or a {@link StackSlot}. Note that a
      * {@link Constant} is automatically tracked.
-     * 
+     *
      * @param location The location to be added to the reference map.
      * @param registerRefMap A register reference map, as created by {@link #initRegisterRefMap()}.
      * @param frameRefMap A frame reference map, as created by {@link #initFrameRefMap()}.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/LoopFragmentInside.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -32,7 +32,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public abstract class AbstractBeginNode extends FixedWithNextNode implements StateSplit, LIRLowerable, Simplifiable, Node.IterableNodeType, GuardingNode {
+public abstract class AbstractBeginNode extends FixedWithNextNode implements StateSplit, LIRLowerable, Simplifiable, GuardingNode {
 
     @Input(notDataflow = true) private FrameState stateAfter;
 
@@ -185,9 +185,4 @@
             throw new UnsupportedOperationException();
         }
     }
-
-    @Override
-    public AbstractBeginNode asNode() {
-        return this;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -28,7 +28,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public abstract class AbstractEndNode extends FixedNode implements Node.IterableNodeType, LIRLowerable {
+public abstract class AbstractEndNode extends FixedNode implements IterableNodeType, LIRLowerable {
 
     protected AbstractEndNode() {
         super(StampFactory.forVoid());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -25,7 +25,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.type.*;
 
-public abstract class ControlSinkNode extends FixedNode implements Node.IterableNodeType {
+public abstract class ControlSinkNode extends FixedNode implements IterableNodeType {
 
     public ControlSinkNode(Stamp stamp) {
         super(stamp);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -37,7 +37,7 @@
  * 
  */
 @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}")
-public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, Lowerable, LIRLowerable, DeoptimizingNode {
+public class DeoptimizeNode extends ControlSinkNode implements IterableNodeType, Lowerable, LIRLowerable, DeoptimizingNode {
 
     @Input private FrameState deoptState;
 
@@ -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/EntryMarkerNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -29,7 +29,7 @@
  * This node will be inserted at point specified by {@link StructuredGraph#getEntryBCI()}, usually
  * by the graph builder.
  */
-public class EntryMarkerNode extends AbstractBeginNode implements Node.IterableNodeType, Simplifiable, LIRLowerable {
+public class EntryMarkerNode extends AbstractBeginNode implements IterableNodeType, Simplifiable, LIRLowerable {
 
     @Override
     public void simplify(SimplifierTool tool) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -31,7 +31,7 @@
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}")
-public final class FixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, Lowerable, Node.IterableNodeType, GuardingNode {
+public final class FixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, Lowerable, IterableNodeType, GuardingNode {
 
     @Input private LogicNode condition;
     private final DeoptimizationReason reason;
@@ -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.GuardsStage.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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/FrameState.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Fri Sep 13 23:12:10 2013 +0200
@@ -35,7 +35,7 @@
  * stack) at a particular point in the abstract interpretation.
  */
 @NodeInfo(nameTemplate = "FrameState@{p#method/s}:{p#bci}")
-public final class FrameState extends VirtualState implements Node.IterableNodeType {
+public final class FrameState extends VirtualState implements IterableNodeType {
 
     protected final int localsSize;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -42,7 +42,7 @@
  * control flow would have reached the guarded node (without taking exceptions into account).
  */
 @NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}")
-public final class GuardNode extends FloatingGuardedNode implements Canonicalizable, Node.IterableNodeType, GuardingNode, GuardedNode {
+public final class GuardNode extends FloatingGuardedNode implements Canonicalizable, IterableNodeType, GuardingNode, GuardedNode {
 
     @Input private LogicNode condition;
     private final DeoptimizationReason reason;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -34,7 +34,7 @@
  * 
  * A GuardedValueNode will only go away if its guard is null or {@link StructuredGraph#start()}.
  */
-public class GuardedValueNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, Node.IterableNodeType, GuardingNode, Canonicalizable, ValueProxy {
+public class GuardedValueNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, GuardingNode, Canonicalizable, ValueProxy {
 
     @Input private ValueNode object;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.GuardsStage.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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -23,14 +23,13 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.graph.Node.IterableNodeType;
 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 {
 
     public final InfopointReason reason;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -35,7 +35,7 @@
  * The {@code InvokeNode} represents all kinds of method calls.
  */
 @NodeInfo(nameTemplate = "Invoke#{p#targetMethod/s}")
-public final class InvokeNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, Invoke, LIRLowerable, MemoryCheckpoint.Single {
+public final class InvokeNode extends AbstractStateSplit implements StateSplit, IterableNodeType, Invoke, LIRLowerable, MemoryCheckpoint.Single {
 
     @Input private CallTargetNode callTarget;
     @Input private FrameState deoptState;
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -32,7 +32,7 @@
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(nameTemplate = "Invoke!#{p#targetMethod/s}")
-public class InvokeWithExceptionNode extends ControlSplitNode implements Node.IterableNodeType, Invoke, MemoryCheckpoint.Single, LIRLowerable {
+public class InvokeWithExceptionNode extends ControlSplitNode implements IterableNodeType, Invoke, MemoryCheckpoint.Single, LIRLowerable {
 
     private static final double EXCEPTION_PROBA = 1e-5;
 
@@ -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/LocalNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LocalNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -29,7 +29,7 @@
  * The {@code Local} instruction is a placeholder for an incoming argument to a function call.
  */
 @NodeInfo(nameTemplate = "Local({p#index})")
-public final class LocalNode extends AbstractLocalNode implements Node.IterableNodeType {
+public final class LocalNode extends AbstractLocalNode implements IterableNodeType {
 
     public LocalNode(int index, Stamp stamp) {
         super(index, stamp);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -28,7 +28,7 @@
 /**
  * Logic node that negates its argument.
  */
-public class LogicNegationNode extends LogicNode implements Canonicalizable, Node.IterableNodeType {
+public class LogicNegationNode extends LogicNode implements Canonicalizable, IterableNodeType {
 
     @Input private LogicNode input;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/LoopBeginNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -31,7 +31,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
-public class LoopBeginNode extends MergeNode implements Node.IterableNodeType, LIRLowerable {
+public class LoopBeginNode extends MergeNode implements IterableNodeType, LIRLowerable {
 
     private double loopFrequency;
     private int nextEndIndex;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/LoopExitNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -22,9 +22,10 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
 
-public class LoopExitNode extends BeginStateSplitNode {
+public class LoopExitNode extends BeginStateSplitNode implements IterableNodeType {
 
     @Input(notDataflow = true) private LoopBeginNode loopBegin;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -33,7 +33,7 @@
 /**
  * Denotes the merging of multiple control-flow paths.
  */
-public class MergeNode extends BeginStateSplitNode implements Node.IterableNodeType, LIRLowerable {
+public class MergeNode extends BeginStateSplitNode implements IterableNodeType, LIRLowerable {
 
     @Input(notDataflow = true) private final NodeInputList<AbstractEndNode> ends = new NodeInputList<>(this);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -34,7 +34,7 @@
  * variable.
  */
 @NodeInfo(nameTemplate = "{p#type/s}Phi({i#values})")
-public class PhiNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType, GuardingNode {
+public class PhiNode extends FloatingNode implements Canonicalizable, 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/PiNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -36,7 +36,7 @@
  * is as narrow or narrower than the PiNode's type. The PiNode, and therefore also the scheduling
  * restriction enforced by the anchor, will go away.
  */
-public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, Node.IterableNodeType, GuardingNode, Canonicalizable, ValueProxy {
+public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, GuardingNode, Canonicalizable, ValueProxy {
 
     @Input private ValueNode object;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -35,7 +35,7 @@
  * loop.
  */
 @NodeInfo(nameTemplate = "{p#type/s}Proxy")
-public class ProxyNode extends FloatingNode implements Node.IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, LIRLowerable, ValueProxy, GuardingNode {
+public class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, LIRLowerable, ValueProxy, GuardingNode {
 
     @Input(notDataflow = true) private AbstractBeginNode proxyPoint;
     @Input private ValueNode value;
@@ -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/ReturnNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public final class ReturnNode extends ControlSinkNode implements LIRLowerable, Node.IterableNodeType {
+public final class ReturnNode extends ControlSinkNode implements LIRLowerable, IterableNodeType {
 
     @Input private ValueNode result;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -30,7 +30,7 @@
 /**
  * Marks a position in the graph where a safepoint should be emitted.
  */
-public class SafepointNode extends DeoptimizingFixedWithNextNode implements LIRLowerable, Node.IterableNodeType {
+public class SafepointNode extends DeoptimizingFixedWithNextNode implements LIRLowerable, IterableNodeType {
 
     public SafepointNode() {
         this(StampFactory.forVoid());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitAndNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ /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	Thu Sep 05 16:36:40 2013 +0200
+++ /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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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 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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Fri Sep 13 23:12:10 2013 +0200
@@ -37,6 +37,35 @@
  */
 public class StructuredGraph extends Graph {
 
+    /**
+     * The different stages of the compilation of a {@link Graph} regarding the status of
+     * {@link GuardNode guards}, {@link DeoptimizingNode deoptimizations} and {@link FrameState
+     * framestates}. The stage of a graph progresses monotonously.
+     * 
+     */
+    public static enum GuardsStage {
+        /**
+         * During this stage, there can be {@link FloatingNode floating} {@link DeoptimizingNode}
+         * such as {@link GuardNode GuardNodes}. New {@link DeoptimizingNode DeoptimizingNodes} can
+         * be introduced without constraints. {@link FrameState} nodes are associated with
+         * {@link StateSplit} nodes.
+         */
+        FLOATING_GUARDS,
+        /**
+         * During this stage, all {@link DeoptimizingNode DeoptimizingNodes} must be
+         * {@link FixedNode fixed} but new {@link DeoptimizingNode DeoptimizingNodes} can still be
+         * introduced. {@link FrameState} nodes are still associated with {@link StateSplit} nodes.
+         */
+        FIXED_DEOPTS,
+        /**
+         * During this stage, all {@link DeoptimizingNode DeoptimizingNodes} must be
+         * {@link FixedNode fixed}. New {@link DeoptimizingNode DeoptimizingNodes} can not be
+         * introduced any more. {@link FrameState} nodes are now associated with
+         * {@link DeoptimizingNode} nodes.
+         */
+        AFTER_FSA
+    }
+
     public static final int INVOCATION_ENTRY_BCI = -1;
     public static final long INVALID_GRAPH_ID = -1;
 
@@ -48,6 +77,7 @@
     private final ResolvedJavaMethod method;
     private final long graphId;
     private final int entryBCI;
+    private GuardsStage guardsPhase = GuardsStage.FLOATING_GUARDS;
 
     /**
      * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start()
@@ -386,4 +416,13 @@
             singleEnd.replaceAndDelete(sux);
         }
     }
+
+    public GuardsStage getGuardsPhase() {
+        return guardsPhase;
+    }
+
+    public void setGuardsPhase(GuardsStage guardsPhase) {
+        assert guardsPhase.ordinal() >= this.guardsPhase.ordinal();
+        this.guardsPhase = guardsPhase;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -32,7 +32,7 @@
 /**
  * A node that attaches a type profile to a proxied input node.
  */
-public final class TypeProfileProxyNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType, ValueProxy {
+public final class TypeProfileProxyNode extends FloatingNode implements Canonicalizable, IterableNodeType, ValueProxy {
 
     @Input private ValueNode object;
     private final JavaTypeProfile profile;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -23,14 +23,13 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
  * Unwinds the current frame to an exception handler in the caller frame.
  */
-public final class UnwindNode extends ControlSinkNode implements Lowerable, LIRLowerable, Node.IterableNodeType {
+public final class UnwindNode extends ControlSinkNode implements Lowerable, LIRLowerable {
 
     @Input private ValueNode exception;
 
@@ -50,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/ValueNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/WriteBarrier.java	Fri Sep 13 23:12:10 2013 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public abstract class WriteBarrier extends FixedWithNextNode implements Lowerable, Node.IterableNodeType {
+public abstract class WriteBarrier extends FixedWithNextNode implements Lowerable, IterableNodeType {
 
     @Input private ValueNode object;
     @Input private LocationNode location;
@@ -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.GuardsStage.AFTER_FSA;
         generator.getRuntime().lower(this, generator);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -150,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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/ArrayRangeWriteNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -29,7 +29,7 @@
 /**
  * Base class for nodes that modify a range of an array.
  */
-public abstract class ArrayRangeWriteNode extends AbstractStateSplit implements Node.IterableNodeType {
+public abstract class ArrayRangeWriteNode extends AbstractStateSplit implements IterableNodeType {
 
     protected ArrayRangeWriteNode(Stamp stamp) {
         super(stamp);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/FloatingReadNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -32,7 +32,7 @@
  * A floating read of a value from memory specified in terms of an object base and an object
  * relative location. This node does not null check the object.
  */
-public final class FloatingReadNode extends FloatingAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable {
+public final class FloatingReadNode extends FloatingAccessNode implements IterableNodeType, LIRLowerable, Canonicalizable {
 
     @Input private Node lastLocationAccess;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.GuardsStage.FIXED_DEOPTS) {
             tool.getRuntime().lower(this, tool);
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/OSRLocalNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(nameTemplate = "OSRLocal({p#index})")
-public class OSRLocalNode extends AbstractLocalNode implements Node.IterableNodeType {
+public class OSRLocalNode extends AbstractLocalNode implements IterableNodeType {
 
     public OSRLocalNode(int index, Stamp stamp) {
         super(index, stamp);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -32,7 +32,7 @@
 /**
  * Reads an {@linkplain AccessNode accessed} value.
  */
-public final class ReadNode extends FloatableAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable, PiPushable, Virtualizable {
+public final class ReadNode extends FloatableAccessNode implements IterableNodeType, LIRLowerable, Canonicalizable, PiPushable, Virtualizable {
 
     public ReadNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType, boolean compressible) {
         super(object, location, stamp, barrierType, compressible);
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -32,7 +32,7 @@
 /**
  * The ValueAnchor instruction keeps non-CFG (floating) nodes above a certain point in the graph.
  */
-public final class ValueAnchorNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType, Virtualizable, GuardingNode {
+public final class ValueAnchorNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, IterableNodeType, Virtualizable, GuardingNode {
 
     @Input private final NodeInputList<ValueNode> anchored;
 
@@ -114,9 +114,4 @@
         }
         tool.delete();
     }
-
-    @Override
-    public ValueNode asNode() {
-        return this;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -33,7 +33,7 @@
 /**
  * Writes a given {@linkplain #value() value} a {@linkplain AccessNode memory location}.
  */
-public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single, Node.IterableNodeType, Virtualizable {
+public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single, IterableNodeType, Virtualizable {
 
     @Input private ValueNode value;
     @Input(notDataflow = true) private FrameState stateAfter;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -31,7 +30,7 @@
 /**
  * The {@code AbstractNewArrayNode} is used for all 1-dimensional array allocations.
  */
-public class AbstractNewArrayNode extends DeoptimizingFixedWithNextNode implements Canonicalizable, Lowerable, ArrayLengthProvider, Node.IterableNodeType {
+public class AbstractNewArrayNode extends DeoptimizingFixedWithNextNode implements Canonicalizable, Lowerable, ArrayLengthProvider {
 
     @Input private ValueNode length;
     private final boolean fillContents;
@@ -88,7 +87,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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -32,7 +31,7 @@
  * Implements a type check where the type being checked is loaded at runtime. This is used, for
  * instance, to implement an object array store check.
  */
-public final class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable, Lowerable, Node.IterableNodeType {
+public final class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable, Lowerable {
 
     @Input private ValueNode object;
     @Input private ValueNode hub;
@@ -59,7 +58,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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -38,7 +38,7 @@
 /**
  * Implements a type check against a compile-time known type.
  */
-public final class CheckCastNode extends FixedWithNextNode implements Canonicalizable, Lowerable, Node.IterableNodeType, Virtualizable, ValueProxy {
+public final class CheckCastNode extends FixedWithNextNode implements Canonicalizable, Lowerable, Virtualizable, ValueProxy {
 
     @Input private ValueNode object;
     private final ResolvedJavaType type;
@@ -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));
@@ -159,7 +159,7 @@
         if (ObjectStamp.isObjectAlwaysNull(object())) {
             return object();
         }
-        if (tool.assumptions().useOptimisticAssumptions()) {
+        if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) {
             ResolvedJavaType exactType = type.findUniqueConcreteSubtype();
             if (exactType != null && exactType != type) {
                 // Propagate more precise type information to usages of the checkcast.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/InstanceOfNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/LoadFieldNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -36,7 +36,7 @@
  * The {@code LoadFieldNode} represents a read of a static or instance field.
  */
 @NodeInfo(nameTemplate = "LoadField#{p#field/s}")
-public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable, Node.IterableNodeType, VirtualizableRoot {
+public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable, IterableNodeType, VirtualizableRoot {
 
     /**
      * Creates a new LoadFieldNode instance.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -31,7 +31,7 @@
 /**
  * The {@code LoadIndexedNode} represents a read from an element of an array.
  */
-public final class LoadIndexedNode extends AccessIndexedNode implements Node.IterableNodeType, Virtualizable {
+public final class LoadIndexedNode extends AccessIndexedNode implements IterableNodeType, Virtualizable {
 
     /**
      * Creates a new LoadIndexedNode.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -32,7 +32,7 @@
 /**
  * Represents the lowered version of an atomic compare-and-swap operation{@code CompareAndSwapNode}.
  */
-public class LoweredCompareAndSwapNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single, Node.IterableNodeType {
+public class LoweredCompareAndSwapNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single, IterableNodeType {
 
     @Input private ValueNode expectedValue;
     @Input private ValueNode newValue;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -30,7 +30,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public class MethodCallTargetNode extends CallTargetNode implements Node.IterableNodeType, Canonicalizable {
+public class MethodCallTargetNode extends CallTargetNode implements IterableNodeType, Canonicalizable {
 
     public enum InvokeKind {
         Interface, Special, Static, Virtual
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -31,7 +31,7 @@
 /**
  * The {@code MonitorEnterNode} represents a monitor release.
  */
-public final class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Lowerable, Node.IterableNodeType, MonitorExit, MemoryCheckpoint.Single, MonitorReference {
+public final class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Lowerable, IterableNodeType, MonitorExit, MemoryCheckpoint.Single, MonitorReference {
 
     private int lockDepth;
 
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -33,7 +33,7 @@
  * The {@code NewInstanceNode} represents the allocation of an instance class object.
  */
 @NodeInfo(nameTemplate = "New {p#instanceClass/s}")
-public final class NewInstanceNode extends DeoptimizingFixedWithNextNode implements Node.IterableNodeType, Canonicalizable, Lowerable, VirtualizableAllocation {
+public final class NewInstanceNode extends DeoptimizingFixedWithNextNode implements Canonicalizable, Lowerable, VirtualizableAllocation {
 
     private final ResolvedJavaType instanceClass;
     private final boolean fillContents;
@@ -77,7 +77,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/NewMultiArrayNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/DelegatingGraalCodeCacheProvider.java	Fri Sep 13 23:12:10 2013 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.spi;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+
+/**
+ * A {@link GraalCodeCacheProvider} that delegates to another {@link GraalCodeCacheProvider}.
+ */
+public class DelegatingGraalCodeCacheProvider extends DelegatingCodeCacheProvider implements GraalCodeCacheProvider {
+
+    public DelegatingGraalCodeCacheProvider(CodeCacheProvider delegate) {
+        super(delegate);
+    }
+
+    @Override
+    protected GraalCodeCacheProvider delegate() {
+        return (GraalCodeCacheProvider) super.delegate();
+    }
+
+    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph) {
+        return delegate().addMethod(method, compResult, graph);
+    }
+
+    public void lower(Node n, LoweringTool tool) {
+        delegate().lower(n, tool);
+    }
+
+    public ValueNode reconstructArrayIndex(LocationNode location) {
+        return delegate().reconstructArrayIndex(location);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -31,7 +31,7 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(nameTemplate = "Alloc {i#virtualObjects}")
-public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Node.IterableNodeType, Simplifiable {
+public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, IterableNodeType, Simplifiable {
 
     @Input private final NodeInputList<VirtualObjectNode> virtualObjects = new NodeInputList<>(this);
     @Input private final NodeInputList<ValueNode> values = new NodeInputList<>(this);
@@ -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/EscapeObjectState.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java	Fri Sep 13 23:12:10 2013 +0200
@@ -25,7 +25,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
-public abstract class EscapeObjectState extends VirtualState implements Node.IterableNodeType {
+public abstract class EscapeObjectState extends VirtualState implements IterableNodeType {
 
     @Input private VirtualObjectNode object;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -28,7 +28,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public abstract class VirtualObjectNode extends ValueNode implements LIRLowerable, Node.IterableNodeType {
+public abstract class VirtualObjectNode extends ValueNode implements LIRLowerable, IterableNodeType {
 
     private boolean hasIdentity;
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/ExpandLogicPhase.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -27,11 +27,22 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
 
+/**
+ * This phase transfers {@link FrameState} nodes from {@link StateSplit} nodes to
+ * {@link DeoptimizingNode DeoptimizingNodes}.
+ * 
+ * This allow to enter the {@link GuardsStage#AFTER_FSA AFTER_FSA} stage of the graph where no new
+ * node that may cause deoptimization can be introduced anymore.
+ * <p>
+ * This Phase processes the graph in post order, assigning the {@link FrameState} from the last
+ * {@link StateSplit} node to {@link DeoptimizingNode DeoptimizingNodes}.
+ */
 public class FrameStateAssignmentPhase extends Phase {
 
     private static class FrameStateAssignmentClosure extends NodeIteratorClosure<FrameState> {
@@ -77,6 +88,8 @@
     protected void run(StructuredGraph graph) {
         assert checkFixedDeopts(graph);
         ReentrantNodeIterator.apply(new FrameStateAssignmentClosure(), graph.start(), null, null);
+
+        graph.setGuardsPhase(GuardsStage.AFTER_FSA);
     }
 
     private static boolean checkFixedDeopts(StructuredGraph graph) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -29,6 +29,7 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
@@ -42,9 +43,9 @@
  * This phase lowers {@link GuardNode GuardNodes} into corresponding control-flow structure and
  * {@link DeoptimizeNode DeoptimizeNodes}.
  * 
- * This allow to enter a phase of the compiler where all node that may cause deoptimization are
- * fixed.
- * 
+ * This allow to enter the {@link GuardsStage#FIXED_DEOPTS FIXED_DEOPTS} stage of the graph where
+ * all node that may cause deoptimization are fixed.
+ * <p>
  * It first makes a schedule in order to know where the control flow should be placed. Then, for
  * each block, it applies two passes. The first one tries to replace null-check guards with implicit
  * null checks performed by access to the objects that need to be null checked. The second phase
@@ -187,6 +188,8 @@
         for (Block block : schedule.getCFG().getBlocks()) {
             processBlock(block, schedule, context.getTarget().implicitNullCheckLimit);
         }
+
+        graph.setGuardsPhase(GuardsStage.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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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;
@@ -68,27 +67,19 @@
     private static final DebugMetric metricInliningPerformed = Debug.metric("InliningPerformed");
     private static final DebugMetric metricInliningConsidered = Debug.metric("InliningConsidered");
     private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize");
-    private static final DebugMetric metricInliningRuns = Debug.metric("Runs");
+    private static final DebugMetric metricInliningRuns = Debug.metric("InliningRuns");
 
-    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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/InsertStateAfterPlaceholderPhase.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InsertStateAfterPlaceholderPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -30,7 +30,7 @@
 
 public class InsertStateAfterPlaceholderPhase extends Phase {
 
-    private static class PlaceholderNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, LIRLowerable, Canonicalizable {
+    private static class PlaceholderNode extends AbstractStateSplit implements StateSplit, IterableNodeType, LIRLowerable, Canonicalizable {
 
         public PlaceholderNode() {
             super(StampFactory.forVoid());
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.*;
@@ -73,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.
@@ -101,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.GuardsStage.FLOATING_GUARDS.ordinal()) {
+                throw new GraalInternalError("Cannot create guards after guard lowering");
             }
             if (OptEliminateGuards.getValue()) {
                 for (Node usage : condition.usages()) {
@@ -134,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) {
@@ -154,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!
@@ -175,7 +167,7 @@
         private final SchedulePhase schedule;
 
         private Round(int iteration, PhaseContext context) {
-            super(String.format("Lowering iteration %d", iteration));
+            super("LoweringIteration" + iteration);
             this.context = context;
             this.schedule = new SchedulePhase();
         }
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/RemoveValueProxyPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -22,7 +22,10 @@
  */
 package com.oracle.graal.phases;
 
+import java.util.regex.*;
+
 import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.nodes.*;
 
 /**
@@ -32,19 +35,35 @@
  */
 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");
+    private final String name;
+
+    private final DebugTimer phaseTimer;
+    private final DebugMetric phaseMetric;
+
+    private static final Pattern NAME_PATTERN = Pattern.compile("[A-Z][A-Za-z0-9]+");
+
+    private static boolean checkName(String name) {
+        assert NAME_PATTERN.matcher(name).matches() : "illegal phase name: " + name;
+        return true;
+    }
 
     protected BasePhase() {
-        this.name = this.getClass().getSimpleName();
-        if (name.endsWith("Phase")) {
-            name = name.substring(0, name.length() - "Phase".length());
+        String nm = this.getClass().getSimpleName();
+        if (nm.endsWith("Phase")) {
+            name = nm.substring(0, nm.length() - "Phase".length());
+        } else {
+            name = nm;
         }
+        assert checkName(name);
+        phaseTimer = Debug.timer("PhaseTime_" + name);
+        phaseMetric = Debug.metric("PhaseCount_" + name);
     }
 
     protected BasePhase(String name) {
+        assert checkName(name);
         this.name = name;
+        phaseTimer = Debug.timer("PhaseTime_" + name);
+        phaseMetric = Debug.metric("PhaseCount_" + name);
     }
 
     protected String getDetailedName() {
@@ -56,17 +75,20 @@
     }
 
     public final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) {
-        Debug.scope(name, this, new Runnable() {
+        try (TimerCloseable a = phaseTimer.start()) {
+
+            Debug.scope(name, this, new Runnable() {
 
-            public void run() {
-                BasePhase.this.run(graph, context);
-                metricPhaseRuns.increment();
-                if (dumpGraph) {
-                    Debug.dump(graph, "After phase %s", name);
+                public void run() {
+                    BasePhase.this.run(graph, context);
+                    phaseMetric.increment();
+                    if (dumpGraph) {
+                        Debug.dump(graph, "After phase %s", name);
+                    }
+                    assert graph.verify();
                 }
-                assert graph.verify();
-            }
-        });
+            });
+        }
     }
 
     public final String getName() {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Fri Sep 13 23:12:10 2013 +0200
@@ -44,6 +44,15 @@
         protected abstract StateT afterSplit(AbstractBeginNode node, StateT oldState);
 
         protected abstract Map<LoopExitNode, StateT> processLoop(LoopBeginNode loop, StateT initialState);
+
+        /**
+         * Determine whether iteration should continue in the current state.
+         * 
+         * @param currentState
+         */
+        protected boolean continueIteration(StateT currentState) {
+            return true;
+        }
     }
 
     private ReentrantNodeIterator() {
@@ -59,12 +68,14 @@
 
         LoopInfo<StateT> info = new LoopInfo<>();
         for (LoopEndNode end : loop.loopEnds()) {
-            assert blockEndStates.containsKey(end) : "no end state for " + end;
-            info.endStates.put(end, blockEndStates.get(end));
+            if (blockEndStates.containsKey(end)) {
+                info.endStates.put(end, blockEndStates.get(end));
+            }
         }
         for (LoopExitNode exit : loop.loopExits()) {
-            assert blockEndStates.containsKey(exit) : "no exit state for " + exit;
-            info.exitStates.put(exit, blockEndStates.get(exit));
+            if (blockEndStates.containsKey(exit)) {
+                info.exitStates.put(exit, blockEndStates.get(exit));
+            }
         }
         return info;
     }
@@ -83,64 +94,69 @@
                 } else {
                     FixedNode next = ((FixedWithNextNode) current).next();
                     state = closure.processNode(current, state);
-                    current = next;
+                    current = closure.continueIteration(state) ? next : null;
                 }
             }
 
             if (current != null) {
                 state = closure.processNode(current, state);
 
-                NodeClassIterator successors = current.successors().iterator();
-                if (!successors.hasNext()) {
-                    if (current instanceof LoopEndNode) {
-                        blockEndStates.put(current, state);
-                    } else if (current instanceof EndNode) {
-                        // add the end node and see if the merge is ready for processing
-                        MergeNode merge = ((EndNode) current).merge();
-                        if (merge instanceof LoopBeginNode) {
-                            Map<LoopExitNode, StateT> loopExitState = closure.processLoop((LoopBeginNode) merge, state);
-                            for (Map.Entry<LoopExitNode, StateT> entry : loopExitState.entrySet()) {
-                                blockEndStates.put(entry.getKey(), entry.getValue());
-                                nodeQueue.add(entry.getKey());
-                            }
-                        } else {
-                            assert !blockEndStates.containsKey(current);
+                if (closure.continueIteration(state)) {
+                    NodeClassIterator successors = current.successors().iterator();
+                    if (!successors.hasNext()) {
+                        if (current instanceof LoopEndNode) {
                             blockEndStates.put(current, state);
-                            boolean endsVisited = true;
-                            for (AbstractEndNode forwardEnd : merge.forwardEnds()) {
-                                if (!blockEndStates.containsKey(forwardEnd)) {
-                                    endsVisited = false;
-                                    break;
+                        } else if (current instanceof EndNode) {
+                            // add the end node and see if the merge is ready for processing
+                            MergeNode merge = ((EndNode) current).merge();
+                            if (merge instanceof LoopBeginNode) {
+                                Map<LoopExitNode, StateT> loopExitState = closure.processLoop((LoopBeginNode) merge, state);
+                                for (Map.Entry<LoopExitNode, StateT> entry : loopExitState.entrySet()) {
+                                    blockEndStates.put(entry.getKey(), entry.getValue());
+                                    nodeQueue.add(entry.getKey());
+                                }
+                            } else {
+                                assert !blockEndStates.containsKey(current);
+                                blockEndStates.put(current, state);
+                                boolean endsVisited = true;
+                                for (AbstractEndNode forwardEnd : merge.forwardEnds()) {
+                                    if (!blockEndStates.containsKey(forwardEnd)) {
+                                        endsVisited = false;
+                                        break;
+                                    }
+                                }
+                                if (endsVisited) {
+                                    ArrayList<StateT> states = new ArrayList<>(merge.forwardEndCount());
+                                    for (int i = 0; i < merge.forwardEndCount(); i++) {
+                                        AbstractEndNode forwardEnd = merge.forwardEndAt(i);
+                                        assert blockEndStates.containsKey(forwardEnd);
+                                        StateT other = blockEndStates.get(forwardEnd);
+                                        states.add(other);
+                                    }
+                                    state = closure.merge(merge, states);
+                                    current = closure.continueIteration(state) ? merge : null;
+                                    continue;
                                 }
                             }
-                            if (endsVisited) {
-                                ArrayList<StateT> states = new ArrayList<>(merge.forwardEndCount());
-                                for (int i = 0; i < merge.forwardEndCount(); i++) {
-                                    AbstractEndNode forwardEnd = merge.forwardEndAt(i);
-                                    assert blockEndStates.containsKey(forwardEnd);
-                                    StateT other = blockEndStates.get(forwardEnd);
-                                    states.add(other);
-                                }
-                                state = closure.merge(merge, states);
-                                current = merge;
-                                continue;
-                            }
                         }
-                    }
-                } else {
-                    FixedNode firstSuccessor = (FixedNode) successors.next();
-                    if (!successors.hasNext()) {
-                        current = firstSuccessor;
-                        continue;
                     } else {
-                        while (successors.hasNext()) {
-                            AbstractBeginNode successor = (AbstractBeginNode) successors.next();
-                            blockEndStates.put(successor, closure.afterSplit(successor, state));
-                            nodeQueue.add(successor);
+                        FixedNode firstSuccessor = (FixedNode) successors.next();
+                        if (!successors.hasNext()) {
+                            current = firstSuccessor;
+                            continue;
+                        } else {
+                            while (successors.hasNext()) {
+                                AbstractBeginNode successor = (AbstractBeginNode) successors.next();
+                                StateT successorState = closure.afterSplit(successor, state);
+                                if (closure.continueIteration(successorState)) {
+                                    blockEndStates.put(successor, successorState);
+                                    nodeQueue.add(successor);
+                                }
+                            }
+                            state = closure.afterSplit((AbstractBeginNode) firstSuccessor, state);
+                            current = closure.continueIteration(state) ? firstSuccessor : null;
+                            continue;
                         }
-                        state = closure.afterSplit((AbstractBeginNode) firstSuccessor, state);
-                        current = firstSuccessor;
-                        continue;
                     }
                 }
             }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.printer/src/com/oracle/graal/printer/DebugEnvironment.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java	Fri Sep 13 23:12:10 2013 +0200
@@ -34,7 +34,10 @@
 public class DebugEnvironment {
 
     public static void initialize(PrintStream log) {
-        Debug.enable();
+        if (!Debug.isEnabled()) {
+            log.println("WARNING: Scope debugging needs to be enabled with -esa or -D" + Debug.Initialization.INITIALIZER_PROPERTY_NAME + "=true");
+            return;
+        }
         List<DebugDumpHandler> dumpHandlers = new ArrayList<>();
         dumpHandlers.add(new GraphPrinterDumpHandler());
         if (PrintCFG.getValue() || PrintBackendCFG.getValue()) {
--- a/graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTX.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTX.java	Fri Sep 13 23:12:10 2013 +0200
@@ -35,83 +35,167 @@
  */
 public class PTX extends Architecture {
 
-    public static final RegisterCategory CPU = new RegisterCategory("CPU");
-    public static final RegisterCategory FPU = new RegisterCategory("FPU");
+    public static final RegisterCategory REG    = new RegisterCategory("REG");
+    public static final RegisterCategory SREG   = new RegisterCategory("SREG");
+    public static final RegisterCategory PARAM  = new RegisterCategory("PARAM");
+
 
     // @formatter:off
 
+    /* Parameter State Space
+     *
+     * The parameter (.param) state space is used (1) to pass input
+     * arguments from the host to the kernel, (2a) to declare formal
+     * input and return parameters for device functions called from
+     * within kernel execution, and (2b) to declare locally-scoped
+     * byte array variables that serve as function call arguments,
+     * typically for passing large structures by value to a function.
+     *
+     * TODO: XXX
+     * The parameters are virtual symbols - just like registers. Bit,
+     * Till we figure out how to model a virtual register set in Graal,
+     * we will pretend that we can use only 8 parameters.
+    */
+
+    public static final Register param0  = new Register(0,  0,  "param0",  PARAM);
+    public static final Register param1  = new Register(1,  1,  "param1",  PARAM);
+    public static final Register param2  = new Register(2,  2,  "param2",  PARAM);
+    public static final Register param3  = new Register(3,  3,  "param3",  PARAM);
+    public static final Register param4  = new Register(4,  4,  "param4",  PARAM);
+    public static final Register param5  = new Register(5,  5,  "param5",  PARAM);
+    public static final Register param6  = new Register(6,  6,  "param6",  PARAM);
+    public static final Register param7  = new Register(7,  7,  "param7",  PARAM);
+
     /*
      * Register State Space
      *
-     * Registers (.reg state space) are fast storage locations. The number of
-     * registers is limited, and will vary from platform to platform. When the
-     * limit is exceeded, register variables will be spilled to memory, causing
-     * changes in performance. For each architecture, there is a recommended
-     * maximum number of registers to use (see the "CUDA Programming Guide" for
-     * details).
+     * Registers (.reg state space) are fast storage locations. The
+     * number of GPU architectural registers is limited, and will vary
+     * from platform to platform. When the limit is exceeded, register
+     * variables will be spilled to memory, causing changes in
+     * performance. For each architecture, there is a recommended
+     * maximum number of registers to use (see the "CUDA Programming
+     * Guide" for details).
+     *
+     * TODD: XXX
+     *
+     * However, PTX supports virtual registers. So, the generated PTX
+     * code does not need to use a specified number of registers. Till
+     * we figure out how to model a virtual register set in Graal, we
+     * will pretend that we can use only 16 registers.
      */
 
-    // General purpose registers
-    public static final Register r0  = new Register(0,  0,  "r0",  CPU);
-    public static final Register r1  = new Register(1,  1,  "r1",  CPU);
-    public static final Register r2  = new Register(2,  2,  "r2",  CPU);
-    public static final Register r3  = new Register(3,  3,  "r3",  CPU);
-    public static final Register r4  = new Register(4,  4,  "r4",  CPU);
-    public static final Register r5  = new Register(5,  5,  "r5",  CPU);
-    public static final Register r6  = new Register(6,  6,  "r6",  CPU);
-    public static final Register r7  = new Register(7,  7,  "r7",  CPU);
+    public static final Register r0  = new Register(8,   8,  "r0",  REG);
+    public static final Register r1  = new Register(9,   9,  "r1",  REG);
+    public static final Register r2  = new Register(10, 10,  "r2",  REG);
+    public static final Register r3  = new Register(11,  11,  "r3",  REG);
+    public static final Register r4  = new Register(12, 12,  "r4",  REG);
+    public static final Register r5  = new Register(13, 13,  "r5",  REG);
+    public static final Register r6  = new Register(14, 14,  "r6",  REG);
+    public static final Register r7  = new Register(15, 15,  "r7",  REG);
 
-    public static final Register r8  = new Register(8,  8,  "r8",  CPU);
-    public static final Register r9  = new Register(9,  9,  "r9",  CPU);
-    public static final Register r10 = new Register(10, 10, "r10", CPU);
-    public static final Register r11 = new Register(11, 11, "r11", CPU);
-    public static final Register r12 = new Register(12, 12, "r12", CPU);
-    public static final Register r13 = new Register(13, 13, "r13", CPU);
-    public static final Register r14 = new Register(14, 14, "r14", CPU);
-    public static final Register r15 = new Register(15, 15, "r15", CPU);
+    public static final Register r8  = new Register(16, 16,  "r8",  REG);
+    public static final Register r9  = new Register(17, 17,  "r9",  REG);
+    public static final Register r10 = new Register(18, 18, "r10", REG);
+    public static final Register r11 = new Register(19, 19, "r11", REG);
+    public static final Register r12 = new Register(20, 20, "r12", REG);
+    public static final Register r13 = new Register(21, 21, "r13", REG);
+    public static final Register r14 = new Register(22, 22, "r14", REG);
+    public static final Register r15 = new Register(23, 23, "r15", REG);
+
+    // Define a virtual register that holds return value
+    public static final Register retReg = new Register(24, 24, "retReg", REG);
 
     public static final Register[] gprRegisters = {
         r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
         r8,  r9,  r10, r11, r12, r13, r14, r15
     };
 
-    // Floating point registers
-    public static final Register f0  = new Register(16, 0,  "f0",  FPU);
-    public static final Register f1  = new Register(17, 1,  "f1",  FPU);
-    public static final Register f2  = new Register(18, 2,  "f2",  FPU);
-    public static final Register f3  = new Register(19, 3,  "f3",  FPU);
-    public static final Register f4  = new Register(20, 4,  "f4",  FPU);
-    public static final Register f5  = new Register(21, 5,  "f5",  FPU);
-    public static final Register f6  = new Register(22, 6,  "f6",  FPU);
-    public static final Register f7  = new Register(23, 7,  "f7",  FPU);
+    public static final Register[] paramRegisters = {
+        param0,  param1,  param2,  param3,  param4,  param5,  param6,  param7
+    };
+
+    // PTX ISA Manual: Section 9:. Special Registers
 
-    public static final Register f8  = new Register(24, 8,  "f8",  FPU);
-    public static final Register f9  = new Register(25, 9,  "f9",  FPU);
-    public static final Register f10 = new Register(26, 10, "f10", FPU);
-    public static final Register f11 = new Register(27, 11, "f11", FPU);
-    public static final Register f12 = new Register(28, 12, "f12", FPU);
-    public static final Register f13 = new Register(29, 13, "f13", FPU);
-    public static final Register f14 = new Register(30, 14, "f14", FPU);
-    public static final Register f15 = new Register(31, 15, "f15", FPU);
+    // PTX includes a number of predefined, read-only variables, which
+    // are visible as special registers and accessed through mov or
+    // cvt instructions.
+    // Thread identifier within a Co-operative Thread Array (CTA) - %tid
+    public static final Register tid  = new Register(100,  100,  "tid", SREG);
+    // Number of thread IDs per CTA - %ntid
+    public static final Register ntid    = new Register(101, 101, "ntid", SREG);
+    // Lane identifier
+    public static final Register laneid  = new Register(102, 102, "laneid", SREG);
+    // Warp identifier
+    public static final Register warpid   = new Register(103, 103, "warid", SREG);
+    // Number of warp IDs
+    public static final Register nwarpid   = new Register(104, 104, "nwarpid", SREG);
+    // CTA identifier
+    public static final Register ctaid   = new Register(105, 105, "ctaid", SREG);
+    // Number of CTA IDs per grid
+    public static final Register nctaid   = new Register(106, 106, "nctaid", SREG);
+    // Single Multiprocessor (SM) ID
+    public static final Register smid    = new Register(107, 107, "smid", SREG);
+    // Number of SM IDs
+    public static final Register nsmid   = new Register(108, 108, "nsmid", SREG);
+    // Grid ID
+    public static final Register gridid  = new Register(109, 109, "gridid", SREG);
+    // 32-bit mask with bit set in position equal to thread's lane number in the warp
+    public static final Register lanemask_eq  = new Register(110, 110, "lanemask_eq", SREG);
+    // 32-bit mask with bits set in positions less than or equal to thread's lane number in the warp
+    public static final Register lanemask_le  = new Register(111, 111, "lanemask_le", SREG);
+    // 32-bit mask with bits set in positions less than thread's lane number in the warp
+    public static final Register lanemask_lt  = new Register(112, 112, "lanemask_lt", SREG);
+    // 32-bit mask with bits set in positions greater than or equal to thread's lane number in the warp
+    public static final Register lanemask_ge  = new Register(113, 113, "lanemask_ge", SREG);
+    // 32-bit mask with bits set in positions greater than thread's lane number in the warp
+    public static final Register lanemask_gt  = new Register(114, 114, "lanemask_gt", SREG);
+    // A predefined, read-only 32-bit unsigned 32-bit unsigned cycle counter
+    public static final Register clock  = new Register(114, 114, "clock", SREG);
+    // A predefined, read-only 64-bit unsigned 32-bit unsigned cycle counter
+    public static final Register clock64  = new Register(115, 115, "clock64", SREG);
+    // Performance monitoring registers
+    public static final Register pm0  = new Register(116, 116,  "pm0", SREG);
+    public static final Register pm1  = new Register(117, 117,  "pm1", SREG);
+    public static final Register pm2  = new Register(118, 118,  "pm2", SREG);
+    public static final Register pm3  = new Register(119, 119,  "pm3", SREG);
+    public static final Register pm4  = new Register(120, 120,  "pm4", SREG);
+    public static final Register pm5  = new Register(121, 121,  "pm5", SREG);
+    public static final Register pm6  = new Register(122, 122,  "pm6", SREG);
+    public static final Register pm7  = new Register(123, 123,  "pm7", SREG);
+    // TODO: Add Driver-defined read-only %envreg<32>
+    //       and %globaltimer, %globaltimer_lo and %globaltimer_hi
 
-    public static final Register[] fpuRegisters = {
-        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
-        f8,  f9,  f10, f11, f12, f13, f14, f15
+    public static final Register[] specialRegisters = {
+        tid, ntid, laneid, warpid, nwarpid, ctaid,
+        nctaid, smid, nsmid, gridid,
+        lanemask_eq, lanemask_le, lanemask_lt, lanemask_ge, lanemask_gt,
+        clock, clock64,
+        pm0, pm1, pm2, pm3, pm4, pm5, pm6, pm7
     };
 
     public static final Register[] allRegisters = {
-        // GPR
+        // Parameter State Space
+        param0, param1, param2, param3,
+        param4, param5, param6, param7,
+        // Register State Space
         r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
         r8,  r9,  r10, r11, r12, r13, r14, r15,
-        // FPU
-        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
-        f8,  f9,  f10, f11, f12, f13, f14, f15
+        // return register
+        retReg,
+        // Special Register State Space - SREG
+        tid, ntid, laneid, warpid, nwarpid, ctaid,
+        nctaid, smid, nsmid, gridid,
+        lanemask_eq, lanemask_le, lanemask_lt, lanemask_ge, lanemask_gt,
+        clock, clock64,
+        pm0, pm1, pm2, pm3, pm4, pm5, pm6, pm7
     };
 
     // @formatter:on
 
     public PTX() {
-        super("PTX", 8, ByteOrder.LITTLE_ENDIAN, false, allRegisters, LOAD_STORE | STORE_STORE, 0, r15.encoding + 1, 8);
+        super("PTX", 8, ByteOrder.LITTLE_ENDIAN, false, allRegisters,
+              LOAD_STORE | STORE_STORE, 0, r15.encoding + 1, 8);
     }
 
     @Override
@@ -121,7 +205,7 @@
         }
 
         Kind kind = (Kind) platformKind;
-        if (category == CPU) {
+        if (category == REG) {
             switch (kind) {
                 case Boolean:
                 case Byte:
@@ -130,10 +214,6 @@
                 case Int:
                 case Long:
                 case Object:
-                    return true;
-            }
-        } else if (category == FPU) {
-            switch (kind) {
                 case Float:
                 case Double:
                     return true;
@@ -145,12 +225,12 @@
 
     @Override
     public PlatformKind getLargestStorableKind(RegisterCategory category) {
-        if (category == CPU) {
-            return Kind.Long;
-        } else if (category == FPU) {
+        if (category == REG) {
             return Kind.Double;
         } else {
             return Kind.Illegal;
         }
     }
+
+
 }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -34,7 +34,7 @@
 
     @Override
     protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
-        CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first();
+        CheckCastNode ccn = graph.getNodes().filter(CheckCastNode.class).first();
         if (ccn != null) {
             CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.type(), ccn.object(), profile, false));
             graph.replaceFixedWithFixed(ccn, ccnNew);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Sep 13 23:12:10 2013 +0200
@@ -44,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.*;
@@ -160,7 +161,7 @@
 
     /**
      * Registers a method substitution.
-     * 
+     *
      * @param originalMember a method or constructor being substituted
      * @param substituteMethod the substitute method
      * @return the original method
@@ -181,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
@@ -215,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
@@ -331,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));
             }
         }
 
@@ -361,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));
             }
         }
 
@@ -380,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);
@@ -397,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);
                             }
                         }
                     }
@@ -427,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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.*;
@@ -65,9 +66,8 @@
 public class PartialEvaluator {
 
     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,8 +76,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);
+        this.canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue(), customCanonicalizer);
         this.skippedExceptionTypes = TruffleCompilerImpl.getSkippedExceptionTypes(metaAccessProvider);
         this.replacements = replacements;
         this.cache = HotSpotGraalRuntime.graalRuntime().getCache();
@@ -113,6 +113,7 @@
 
         Debug.scope("createGraph", graph, new Runnable() {
 
+            @SuppressWarnings("deprecation")
             @Override
             public void run() {
                 new GraphBuilderPhase(metaAccessProvider, config, TruffleCompilerImpl.Optimizations).apply(graph);
@@ -122,8 +123,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);
@@ -148,29 +149,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());
@@ -179,7 +180,7 @@
 
                 // 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());
@@ -202,7 +203,7 @@
                 new ConvertDeoptimizeToGuardPhase().apply(graph);
 
                 // Canonicalize / constant propagate.
-                canonicalizerPhase.apply(graph);
+                canonicalizer.apply(graph, context);
             }
         });
 
@@ -228,7 +229,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();
                         }
 
@@ -256,7 +257,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() {
@@ -265,13 +266,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);
@@ -286,9 +288,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/PartialEvaluatorCanonicalizer.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java	Fri Sep 13 23:12:10 2013 +0200
@@ -27,7 +27,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.nodes.Node.Child;
@@ -35,40 +34,30 @@
 final class PartialEvaluatorCanonicalizer implements CanonicalizerPhase.CustomCanonicalizer {
 
     private final MetaAccessProvider metaAccessProvider;
-    private final ResolvedJavaType nodeClass;
 
-    PartialEvaluatorCanonicalizer(MetaAccessProvider metaAccessProvider, ResolvedJavaType nodeClass) {
+    PartialEvaluatorCanonicalizer(MetaAccessProvider metaAccessProvider) {
         this.metaAccessProvider = metaAccessProvider;
-        this.nodeClass = nodeClass;
     }
 
     @Override
     public ValueNode canonicalize(ValueNode node) {
         if (node instanceof LoadFieldNode) {
             LoadFieldNode loadFieldNode = (LoadFieldNode) node;
-            if (!loadFieldNode.isStatic() &&
-                            loadFieldNode.object().isConstant() &&
-                            !loadFieldNode.object().isNullConstant() &&
-                            ((loadFieldNode.kind() == Kind.Object && loadFieldNode.field().getAnnotation(Child.class) != null) || Modifier.isFinal(loadFieldNode.field().getModifiers()) || loadFieldNode.field().getAnnotation(
-                                            CompilerDirectives.CompilationFinal.class) != null)) {
-                Constant constant = loadFieldNode.field().readValue(loadFieldNode.object().asConstant());
-                return ConstantNode.forConstant(constant, metaAccessProvider, node.graph());
-            }
-        } else if (node instanceof LoadIndexedNode) {
-            LoadIndexedNode loadIndexedNode = (LoadIndexedNode) node;
-            Stamp stamp = loadIndexedNode.array().stamp();
-            if (stamp.kind() == Kind.Object && loadIndexedNode.array().isConstant() && !loadIndexedNode.array().isNullConstant() && loadIndexedNode.index().isConstant()) {
-                ObjectStamp objectStamp = (ObjectStamp) stamp;
-                ResolvedJavaType type = objectStamp.type();
-                if (type != null && type.isArray() && this.nodeClass.isAssignableFrom(type.getComponentType())) {
-                    Object array = loadIndexedNode.array().asConstant().asObject();
-                    int index = loadIndexedNode.index().asConstant().asInt();
-                    Object value = Array.get(array, index);
-                    return ConstantNode.forObject(value, metaAccessProvider, node.graph());
+            if (!loadFieldNode.isStatic() && loadFieldNode.object().isConstant() && !loadFieldNode.object().isNullConstant()) {
+                if (Modifier.isFinal(loadFieldNode.field().getModifiers()) || (loadFieldNode.kind() == Kind.Object && loadFieldNode.field().getAnnotation(Child.class) != null) ||
+                                loadFieldNode.field().getAnnotation(CompilerDirectives.CompilationFinal.class) != null) {
+                    Constant constant = loadFieldNode.field().readValue(loadFieldNode.object().asConstant());
+                    assert verifyFieldValue(loadFieldNode.field(), constant);
+                    return ConstantNode.forConstant(constant, metaAccessProvider, node.graph());
                 }
             }
         }
 
         return node;
     }
+
+    private static boolean verifyFieldValue(ResolvedJavaField field, Constant constant) {
+        assert field.getAnnotation(Child.class) == null || constant.isNull() || constant.asObject() instanceof com.oracle.truffle.api.nodes.Node : "@Child field value must be a Node: " + field;
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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();
 
@@ -180,6 +180,8 @@
 
     private static void contractGraph(StructuredGraph newGraph, ConditionalEliminationPhase conditionalEliminationPhase, ConvertDeoptimizeToGuardPhase convertDeoptimizeToGuardPhase,
                     CanonicalizerPhase canonicalizerPhase, EarlyReadEliminationPhase readEliminationPhase, PhaseContext context) {
+        new ReplaceLoadFinalPhase().apply(newGraph);
+
         // Canonicalize / constant propagate.
         canonicalizerPhase.apply(newGraph, context);
 
@@ -306,14 +308,18 @@
 
     private static boolean checkArgumentStamps(StructuredGraph graph, NodeInputList<ValueNode> arguments) {
         assert graph.getNodes(LocalNode.class).count() <= arguments.count();
-        for (LocalNode localNode : graph.getNodes(LocalNode.class)) {
-            Stamp newStamp = localNode.stamp().meet(arguments.get(localNode.index()).stamp());
-            if (!newStamp.equals(localNode.stamp())) {
-                if (TruffleCompilerOptions.TraceTruffleCacheDetails.getValue()) {
-                    TTY.println(String.format("[truffle] graph cache entry too specific for method %s argument %s previous stamp %s new stamp %s.", graph.method(), localNode, localNode.stamp(),
-                                    newStamp));
+        FrameState startState = graph.start().stateAfter();
+        for (int i = 0; i < arguments.size(); i++) {
+            ValueNode localNode = startState.localAt(i);
+            if (localNode != null) {
+                Stamp newStamp = localNode.stamp().meet(arguments.get(i).stamp());
+                if (!newStamp.equals(localNode.stamp())) {
+                    if (TruffleCompilerOptions.TraceTruffleCacheDetails.getValue()) {
+                        TTY.println(String.format("[truffle] graph cache entry too specific for method %s argument %s previous stamp %s new stamp %s.", graph.method(), localNode, localNode.stamp(),
+                                        newStamp));
+                    }
+                    return false;
                 }
-                return false;
             }
         }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.*;
@@ -84,7 +83,7 @@
 
         this.partialEvaluator = new PartialEvaluator(metaAccessProvider, replacements, truffleCache);
 
-        if (DebugEnabled.getValue()) {
+        if (Debug.isEnabled()) {
             DebugEnvironment.initialize(System.out);
         }
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -29,7 +29,7 @@
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.truffle.*;
 
-public class AssumptionNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType, Simplifiable {
+public class AssumptionNode extends MacroNode implements com.oracle.graal.graph.IterableNodeType, Simplifiable {
 
     public AssumptionNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
 
-public class BailoutNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType, Canonicalizable {
+public class BailoutNode extends MacroNode implements Canonicalizable {
 
     public BailoutNode(Invoke invoke) {
         super(invoke);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -0,0 +1,86 @@
+/*
+ * 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.truffle.nodes;
+
+import java.lang.reflect.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * @see LoadIndexedNode
+ */
+public final class LoadIndexedFinalNode extends AccessIndexedNode implements Canonicalizable {
+
+    /**
+     * Creates a new {@link LoadIndexedFinalNode}.
+     * 
+     * @param array the instruction producing the array
+     * @param index the instruction producing the index
+     * @param elementKind the element type
+     */
+    public LoadIndexedFinalNode(ValueNode array, ValueNode index, Kind elementKind) {
+        super(createStamp(array, elementKind), array, index, elementKind);
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (array().isConstant() && !array().isNullConstant() && index().isConstant()) {
+            Object array = array().asConstant().asObject();
+            long index = index().asConstant().asLong();
+            if (index >= 0 && index < Array.getLength(array)) {
+                int arrayBaseOffset = Unsafe.getUnsafe().arrayBaseOffset(array.getClass());
+                int arrayIndexScale = Unsafe.getUnsafe().arrayIndexScale(array.getClass());
+                Constant constant = tool.runtime().readUnsafeConstant(elementKind(), array, arrayBaseOffset + index * arrayIndexScale, elementKind() == Kind.Object);
+                return ConstantNode.forConstant(constant, tool.runtime(), graph());
+            }
+        }
+        return this;
+    }
+
+    private static Stamp createStamp(ValueNode array, Kind kind) {
+        ResolvedJavaType type = ObjectStamp.typeOrNull(array);
+        if (kind == Kind.Object && type != null) {
+            return StampFactory.declared(type.getComponentType());
+        } else {
+            return StampFactory.forKind(kind);
+        }
+    }
+
+    @Override
+    public boolean inferStamp() {
+        return updateStamp(createStamp(array(), elementKind()));
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        LoadIndexedNode loadIndexedNode = graph().add(new LoadIndexedNode(array(), index(), elementKind()));
+        graph().replaceFixedWithFixed(this, loadIndexedNode);
+        loadIndexedNode.lower(tool);
+    }
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/IntegerExactArithmeticNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
-interface IntegerExactArithmeticNode extends Lowerable, Node.IterableNodeType {
+interface IntegerExactArithmeticNode extends Lowerable, IterableNodeType {
 
     IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt);
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.GuardsStage.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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -26,14 +26,14 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
 
-public class NeverInlineMacroNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType {
+public class NeverInlineMacroNode extends MacroNode implements com.oracle.graal.graph.IterableNodeType {
 
     public NeverInlineMacroNode(Invoke invoke) {
         super(invoke);
     }
 
     @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/asserts/NeverPartOfCompilationNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -25,7 +25,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
 
-public class NeverPartOfCompilationNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType {
+public class NeverPartOfCompilationNode extends MacroNode implements com.oracle.graal.graph.IterableNodeType {
 
     private final String message;
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameGetNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameGetNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.*;
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameSetNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.*;
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.*;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.*;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomTypeCheckNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomTypeCheckNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 
-public final class CustomTypeCheckNode extends LogicNode implements Lowerable, Virtualizable, com.oracle.graal.graph.Node.IterableNodeType {
+public final class CustomTypeCheckNode extends LogicNode implements Lowerable, Virtualizable, com.oracle.graal.graph.IterableNodeType {
 
     @Input private ValueNode condition;
     @Input private ValueNode object;
@@ -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.GuardsStage.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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -28,7 +28,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public final class TypeCastNode extends FixedWithNextNode implements Lowerable, com.oracle.graal.graph.Node.IterableNodeType, ValueProxy, Virtualizable {
+public final class TypeCastNode extends FixedWithNextNode implements Lowerable, com.oracle.graal.graph.IterableNodeType, ValueProxy, Virtualizable {
 
     @Input private ValueNode receiver;
     @Input private ValueNode object;
@@ -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.GuardsStage.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/nodes/typesystem/UnsafeCustomizationNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeCustomizationNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public final class UnsafeCustomizationNode extends FloatingNode implements LIRLowerable, com.oracle.graal.graph.Node.IterableNodeType {
+public final class UnsafeCustomizationNode extends FloatingNode implements LIRLowerable, com.oracle.graal.graph.IterableNodeType {
 
     @Input private ValueNode receiver;
     private final Object customType;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/InlineTrivialGettersPhase.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/InlineTrivialGettersPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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);
                         }
                     }
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceLoadFinalPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -0,0 +1,53 @@
+/*
+ * 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.truffle.phases;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.truffle.nodes.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.nodes.Node.Children;
+
+public class ReplaceLoadFinalPhase extends Phase {
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (LoadIndexedNode loadIndexedNode : graph.getNodes(LoadIndexedNode.class)) {
+            if (loadIndexedNode.array() instanceof LoadFieldNode) {
+                LoadFieldNode loadFieldNode = (LoadFieldNode) loadIndexedNode.array();
+                if (!loadFieldNode.isStatic() && isCompilationFinal(loadFieldNode.field())) {
+                    graph.replaceFixedWithFixed(loadIndexedNode, graph.add(new LoadIndexedFinalNode(loadIndexedNode.array(), loadIndexedNode.index(), loadIndexedNode.elementKind())));
+                }
+            }
+        }
+    }
+
+    private static boolean isCompilationFinal(ResolvedJavaField field) {
+        assert (field.getAnnotation(Children.class) == null && field.getAnnotation(CompilerDirectives.CompilationFinal.class) == null) || Modifier.isFinal(field.getModifiers()) : "field needs to be declared as final";
+        return Modifier.isFinal(field.getModifiers()) && (field.getAnnotation(Children.class) != null || field.getAnnotation(CompilerDirectives.CompilationFinal.class) != null);
+    }
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyNoIntrinsicsLeftPhase.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyNoIntrinsicsLeftPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.*;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java	Fri Sep 13 23:12:10 2013 +0200
@@ -29,7 +29,7 @@
 /**
  * This class encapsulated the materialized state of an escape analyzed object.
  */
-public final class MaterializedObjectState extends EscapeObjectState implements Node.IterableNodeType, Node.ValueNumberable {
+public final class MaterializedObjectState extends EscapeObjectState implements IterableNodeType, Node.ValueNumberable {
 
     @Input private ValueNode materializedValue;
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java	Fri Sep 13 23:12:10 2013 +0200
@@ -31,7 +31,7 @@
 /**
  * This class encapsulated the virtual state of an escape analyzed object.
  */
-public final class VirtualObjectState extends EscapeObjectState implements Node.IterableNodeType, Node.ValueNumberable {
+public final class VirtualObjectState extends EscapeObjectState implements IterableNodeType, Node.ValueNumberable {
 
     @Input private final NodeInputList<ValueNode> fieldValues;
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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;
     }
 
--- /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	Fri Sep 13 23:12:10 2013 +0200
@@ -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/PolymorphicTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/TypeSystemTest.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Fri Sep 13 23:12:10 2013 +0200
@@ -48,6 +48,11 @@
             return (int) value;
         }
 
+        @ImplicitCast
+        Str castStr(String strvalue) {
+            return new Str(strvalue);
+        }
+
     }
 
     @TypeSystemReference(SimpleTypes.class)
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java	Fri Sep 13 23:12:10 2013 +0200
@@ -25,75 +25,30 @@
 package com.oracle.truffle.api;
 
 /**
- * Represents a contiguous text section within the source code of a guest language program.
+ * Description of contiguous text section within the source code of a guest language program.
  */
-public class SourceSection {
-
-    private final Source source;
-    private final String identifier;
-    private final int startLine;
-    private final int startColumn;
-    private final int charIndex;
-    private final int charLength;
-
-    /**
-     * Creates a new object representing a contiguous text section within the source code of a guest
-     * language program.
-     * <p>
-     * The starting location of the section is specified using two different coordinate:
-     * <ul>
-     * <li><b>(row, column)</b>: rows and columns are 1-based, so the first character in a source
-     * file is at position {@code (1,1)}.</li>
-     * <li><b>character index</b>: 0-based offset of the character from the beginning of the source,
-     * so the first character in a file is at index {@code 0}.</li>
-     * </ul>
-     * The <b>newline</b> that terminates each line counts as a single character for the purpose of
-     * a character index. The (row,column) coordinates of a newline character should never appear in
-     * a text section.
-     * <p>
-     * 
-     * @param source object representing the complete source program that contains this section
-     * @param identifier an identifier used when printing the section
-     * @param startLine the 1-based number of the start line of the section
-     * @param startColumn the 1-based number of the start column of the section
-     * @param charIndex the 0-based index of the first character of the section
-     * @param charLength the length of the section in number of characters
-     */
-    public SourceSection(Source source, String identifier, int startLine, int startColumn, int charIndex, int charLength) {
-        this.source = source;
-        this.identifier = identifier;
-        this.startLine = startLine;
-        this.startColumn = startColumn;
-        this.charIndex = charIndex;
-        this.charLength = charLength;
-    }
+public interface SourceSection {
 
     /**
      * Returns the object representing the source program that contains this section.
      * 
      * @return the source object
      */
-    public final Source getSource() {
-        return source;
-    }
+    Source getSource();
 
     /**
      * Returns 1-based line number of the first character in this source section (inclusive).
      * 
      * @return the starting line number
      */
-    public final int getStartLine() {
-        return startLine;
-    }
+    int getStartLine();
 
     /**
      * Returns the 1-based column number of the first character in this source section (inclusive).
      * 
      * @return the starting column number
      */
-    public final int getStartColumn() {
-        return startColumn;
-    }
+    int getStartColumn();
 
     /**
      * Returns the 0-based index of the first character in this source section.
@@ -103,9 +58,7 @@
      * 
      * @return the starting character index
      */
-    public final int getCharIndex() {
-        return charIndex;
-    }
+    int getCharIndex();
 
     /**
      * Returns the length of this source section in characters.
@@ -115,85 +68,28 @@
      * 
      * @return the number of characters in the section
      */
-    public final int getCharLength() {
-        return charLength;
-    }
+    int getCharLength();
+
+    /**
+     * Returns the index of the text position immediately following the last character in the
+     * section.
+     * 
+     * @return the end position of the section
+     */
+    int getCharEndIndex();
 
     /**
      * Returns the identifier of this source section that is used for printing the section.
      * 
      * @return the identifier of the section
      */
-    public final String getIdentifier() {
-        return identifier;
-    }
+    String getIdentifier();
 
     /**
      * Returns text of the code represented by this source section.
      * 
      * @return the code as a String object
      */
-    public final String getCode() {
-        return getSource().getCode().substring(charIndex, charIndex + charLength);
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s:%d", source.getName(), startLine);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + charIndex;
-        result = prime * result + charLength;
-        result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
-        result = prime * result + ((source == null) ? 0 : source.hashCode());
-        result = prime * result + startColumn;
-        result = prime * result + startLine;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof SourceSection)) {
-            return false;
-        }
-        SourceSection other = (SourceSection) obj;
-        if (charIndex != other.charIndex) {
-            return false;
-        }
-        if (charLength != other.charLength) {
-            return false;
-        }
-        if (identifier == null) {
-            if (other.identifier != null) {
-                return false;
-            }
-        } else if (!identifier.equals(other.identifier)) {
-            return false;
-        }
-        if (source == null) {
-            if (other.source != null) {
-                return false;
-            }
-        } else if (!source.equals(other.source)) {
-            return false;
-        }
-        if (startColumn != other.startColumn) {
-            return false;
-        }
-        if (startLine != other.startLine) {
-            return false;
-        }
-        return true;
-    }
+    String getCode();
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultSourceSection.java	Fri Sep 13 23:12:10 2013 +0200
@@ -0,0 +1,164 @@
+/*
+ * 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.  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.impl;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * Represents a contiguous text section within the source code of a guest language program.
+ */
+public class DefaultSourceSection implements SourceSection {
+
+    private final Source source;
+    private final String identifier;
+    private final int startLine;
+    private final int startColumn;
+    private final int charIndex;
+    private final int charLength;
+
+    /**
+     * Creates a new object representing a contiguous text section within the source code of a guest
+     * language program's text.
+     * <p>
+     * The starting location of the section is specified using two different coordinate:
+     * <ul>
+     * <li><b>(row, column)</b>: rows and columns are 1-based, so the first character in a source
+     * file is at position {@code (1,1)}.</li>
+     * <li><b>character index</b>: 0-based offset of the character from the beginning of the source,
+     * so the first character in a file is at index {@code 0}.</li>
+     * </ul>
+     * The <b>newline</b> that terminates each line counts as a single character for the purpose of
+     * a character index. The (row,column) coordinates of a newline character should never appear in
+     * a text section.
+     * <p>
+     * 
+     * @param source object representing the complete source program that contains this section
+     * @param identifier an identifier used when printing the section
+     * @param startLine the 1-based number of the start line of the section
+     * @param startColumn the 1-based number of the start column of the section
+     * @param charIndex the 0-based index of the first character of the section
+     * @param charLength the length of the section in number of characters
+     */
+    public DefaultSourceSection(Source source, String identifier, int startLine, int startColumn, int charIndex, int charLength) {
+        this.source = source;
+        this.identifier = identifier;
+        this.startLine = startLine;
+        this.startColumn = startColumn;
+        this.charIndex = charIndex;
+        this.charLength = charLength;
+    }
+
+    public final Source getSource() {
+        return source;
+    }
+
+    public final int getStartLine() {
+        return startLine;
+    }
+
+    public final int getStartColumn() {
+        return startColumn;
+    }
+
+    public final int getCharIndex() {
+        return charIndex;
+    }
+
+    public final int getCharLength() {
+        return charLength;
+    }
+
+    public final int getCharEndIndex() {
+        return charIndex + charLength;
+    }
+
+    public final String getIdentifier() {
+        return identifier;
+    }
+
+    public final String getCode() {
+        return getSource().getCode().substring(charIndex, charIndex + charLength);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s:%d", source.getName(), startLine);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + charIndex;
+        result = prime * result + charLength;
+        result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
+        result = prime * result + ((source == null) ? 0 : source.hashCode());
+        result = prime * result + startColumn;
+        result = prime * result + startLine;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof DefaultSourceSection)) {
+            return false;
+        }
+        DefaultSourceSection other = (DefaultSourceSection) obj;
+        if (charIndex != other.charIndex) {
+            return false;
+        }
+        if (charLength != other.charLength) {
+            return false;
+        }
+        if (identifier == null) {
+            if (other.identifier != null) {
+                return false;
+            }
+        } else if (!identifier.equals(other.identifier)) {
+            return false;
+        }
+        if (source == null) {
+            if (other.source != null) {
+                return false;
+            }
+        } else if (!source.equals(other.source)) {
+            return false;
+        }
+        if (startColumn != other.startColumn) {
+            return false;
+        }
+        if (startLine != other.startLine) {
+            return false;
+        }
+        return true;
+    }
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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.
      * 
@@ -66,7 +71,12 @@
      */
     public final void assignSourceSection(SourceSection section) {
         if (sourceSection != null) {
-            throw new IllegalStateException("Source section is already assigned.");
+            // Patch this test during the transition to constructor-based
+            // source attribution, which would otherwise trigger this
+            // exception. This method will eventually be deprecated.
+            if (getSourceSection() != section) {
+                throw new IllegalStateException("Source section is already assigned.");
+            }
         }
         this.sourceSection = section;
     }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Fri Sep 13 23:12:10 2013 +0200
@@ -423,6 +423,24 @@
         return result;
     }
 
+    /**
+     * Get the nth parent of a node, where the 0th parent is the node itself. Returns null if there
+     * are less than n ancestors.
+     */
+    public static Node getNthParent(Node node, int n) {
+        Node parent = node;
+
+        for (int i = 0; i < n; i++) {
+            parent = parent.getParent();
+
+            if (parent == null) {
+                return null;
+            }
+        }
+
+        return parent;
+    }
+
     /** find annotation in class/interface hierarchy. */
     public static <T extends Annotation> T findAnnotation(Class<?> clazz, Class<T> annotationClass) {
         if (clazz.getAnnotation(annotationClass) != null) {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/Utils.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeBuilder.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeBuilder.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/NodeChildData.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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) {
@@ -853,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);
                 }
             }
@@ -1107,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();
@@ -1141,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)");
@@ -1184,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;
@@ -1223,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;
@@ -1434,7 +1492,7 @@
                     guardsAnd = " && ";
                 }
 
-                CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType());
+                CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType(), checkMinimumState);
                 if (cast != null) {
                     castBuilder.tree(cast);
                 }
@@ -1526,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
 
@@ -1539,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 checkMinimumState) {
             NodeData node = field.getNodeData();
             TypeData sourceType = source.getTypeSystemType();
 
@@ -1554,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 (checkMinimumState && 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) {
@@ -1595,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 {
@@ -1669,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) {
@@ -1696,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 {
@@ -1732,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();
 
@@ -1776,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) {
@@ -1827,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();
         }
@@ -1969,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();
@@ -1980,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);
@@ -2049,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;
@@ -2109,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();
 
@@ -2199,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;
@@ -2277,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);
                 }
             }
@@ -2333,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;
@@ -2375,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();
 
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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/NodeParser.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Fri Sep 13 23:12:10 2013 +0200
@@ -332,7 +332,7 @@
         nodeData.setNodeContainer(nodeContainer != null);
         nodeData.setTypeSystem(typeSystem);
         nodeData.setFields(parseFields(typeHierarchy, elements));
-        nodeData.setChildren(parseChildren(elements, typeHierarchy));
+        nodeData.setChildren(parseChildren(nodeData, elements, typeHierarchy));
         nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
 
         // resolveChildren invokes cyclic parsing.
@@ -407,7 +407,7 @@
         }
     }
 
-    private List<NodeChildData> parseChildren(List<? extends Element> elements, final List<TypeElement> typeHierarchy) {
+    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);
@@ -472,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);
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java	Fri Sep 13 23:12:10 2013 +0200
@@ -129,7 +129,7 @@
 
         TypeElement rootEnclosing = Utils.findRootEnclosingType(getMessageElement());
         TypeElement baseEnclosing = Utils.findRootEnclosingType(baseType);
-        if (rootEnclosing == null || !Utils.typeEquals(baseEnclosing.asType(), rootEnclosing.asType()) || this != message.getOriginalContainer()) {
+        if (rootEnclosing == null || !Utils.typeEquals(baseEnclosing.asType(), rootEnclosing.asType())) {
             // redirect message
             MessageContainer original = message.getOriginalContainer();
             messageElement = baseType;
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastData.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastData.java	Fri Sep 13 23:12:10 2013 +0200
@@ -26,8 +26,32 @@
 
 public class ImplicitCastData extends TemplateMethod {
 
-    public ImplicitCastData(TemplateMethod method) {
+    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);
     }
 
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java	Fri Sep 13 23:12:10 2013 +0200
@@ -56,7 +56,20 @@
 
     @Override
     public ImplicitCastData create(TemplateMethod method, boolean invalid) {
-        return new ImplicitCastData(method);
+        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/TypeSystemCodeGenerator.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java	Fri Sep 13 23:12:10 2013 +0200
@@ -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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java	Fri Sep 13 23:12:10 2013 +0200
@@ -36,6 +36,7 @@
     private List<TypeMirror> primitiveTypeMirrors = new ArrayList<>();
     private List<TypeMirror> boxedTypeMirrors = new ArrayList<>();
 
+    private List<ImplicitCastData> implicitCasts;
     private List<TypeCastData> casts;
     private List<TypeCheckData> checks;
 
@@ -61,6 +62,14 @@
         }
     }
 
+    public void setImplicitCasts(List<ImplicitCastData> implicitCasts) {
+        this.implicitCasts = implicitCasts;
+    }
+
+    public List<ImplicitCastData> getImplicitCasts() {
+        return implicitCasts;
+    }
+
     public void setCasts(List<TypeCastData> casts) {
         this.casts = casts;
     }
@@ -89,6 +98,9 @@
         if (casts != null) {
             sinks.addAll(casts);
         }
+        if (implicitCasts != null) {
+            sinks.addAll(implicitCasts);
+        }
         return sinks;
     }
 
@@ -161,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	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java	Fri Sep 13 23:12:10 2013 +0200
@@ -71,7 +71,7 @@
         }
 
         typeSystem.setTypes(parseTypes(typeSystem));
-        if (typeSystem.getTypes() == null) {
+        if (typeSystem.hasErrors()) {
             return typeSystem;
         }
 
@@ -91,6 +91,8 @@
         if (casts == null || checks == null || implicitCasts == null) {
             return typeSystem;
         }
+
+        typeSystem.setImplicitCasts(implicitCasts);
         typeSystem.setCasts(casts);
         typeSystem.setChecks(checks);
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java	Fri Sep 13 23:12:10 2013 +0200
@@ -69,4 +69,9 @@
     public boolean isBigInteger(@SuppressWarnings("unused") int value) {
         return true;
     }
+
+    @ImplicitCast
+    public BigInteger castBigInteger(int value) {
+        return BigInteger.valueOf(value);
+    }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Fri Sep 13 23:12:10 2013 +0200
@@ -32,11 +32,11 @@
 // Checkstyle: stop
 // @formatter:off
 public class Parser {
-	public static final int _EOF = 0;
-	public static final int _identifier = 1;
-	public static final int _stringLiteral = 2;
-	public static final int _numericLiteral = 3;
-	public static final int maxT = 28;
+	public static final int _EOF = 0;
+	public static final int _identifier = 1;
+	public static final int _stringLiteral = 2;
+	public static final int _numericLiteral = 3;
+	public static final int maxT = 28;
 
     static final boolean T = true;
     static final boolean x = false;
@@ -120,255 +120,255 @@
         }
     }
 
-	void SimpleLanguage() {
-		Function();
-		while (la.kind == 4) {
-			Function();
-		}
-	}
-
-	void Function() {
-		Expect(4);
-		factory.startFunction(); 
-		Expect(1);
-		String name = t.val; 
-		StatementNode body = Block();
-		factory.createFunction(body, name); 
-	}
-
-	StatementNode  Block() {
-		StatementNode  result;
-		List<StatementNode> statements = new ArrayList<>(); 
-		Expect(5);
-		while (StartOf(1)) {
-			StatementNode statement = Statement();
-			statements.add(statement); 
-		}
-		Expect(6);
-		result = factory.createBlock(statements); 
-		return result;
-	}
-
-	StatementNode  Statement() {
-		StatementNode  result;
-		result = null; 
-		if (la.kind == 7) {
-			result = WhileStatement();
-		} else if (la.kind == 1) {
-			result = AssignmentStatement();
-		} else if (la.kind == 12) {
-			result = OutputStatement();
-		} else if (la.kind == 13) {
-			result = ReturnStatement();
-		} else SynErr(29);
-		return result;
-	}
-
-	StatementNode  WhileStatement() {
-		StatementNode  result;
-		Expect(7);
-		Expect(8);
-		ConditionNode condition = Expression();
-		Expect(9);
-		StatementNode body = Block();
-		result = factory.createWhile(condition, body); 
-		return result;
-	}
-
-	StatementNode  AssignmentStatement() {
-		StatementNode  result;
-		Expect(1);
-		String name = t.val; 
-		Expect(10);
-		TypedNode rvalue = Expression();
-		Expect(11);
-		result = factory.createAssignment(name, rvalue); 
-		return result;
-	}
-
-	StatementNode  OutputStatement() {
-		StatementNode  result;
-		List<TypedNode> expressions = new ArrayList<>(); 
-		Expect(12);
-		while (StartOf(2)) {
-			TypedNode value = Expression();
-			expressions.add(value); 
-		}
-		Expect(11);
-		result = factory.createPrint(expressions); 
-		return result;
-	}
-
-	StatementNode  ReturnStatement() {
-		StatementNode  result;
-		Expect(13);
-		TypedNode value = Expression();
-		Expect(11);
-		result = factory.createReturn(value); 
-		return result;
-	}
-
-	TypedNode  Expression() {
-		TypedNode  result;
-		result = ValueExpression();
-		if (StartOf(3)) {
-			switch (la.kind) {
-			case 14: {
-				Get();
-				break;
-			}
-			case 15: {
-				Get();
-				break;
-			}
-			case 16: {
-				Get();
-				break;
-			}
-			case 17: {
-				Get();
-				break;
-			}
-			case 18: {
-				Get();
-				break;
-			}
-			case 19: {
-				Get();
-				break;
-			}
-			}
-			String op = t.val; 
-			TypedNode right = ValueExpression();
-			result = factory.createBinary(op, result, right); 
-		}
-		return result;
-	}
-
-	TypedNode  ValueExpression() {
-		TypedNode  result;
-		result = Term();
-		while (la.kind == 20 || la.kind == 21) {
-			if (la.kind == 20) {
-				Get();
-			} else {
-				Get();
-			}
-			String op = t.val; 
-			TypedNode right = Term();
-			result = factory.createBinary(op, result, right); 
-		}
-		return result;
-	}
-
-	TypedNode  Term() {
-		TypedNode  result;
-		result = Factor();
-		while (la.kind == 22 || la.kind == 23) {
-			if (la.kind == 22) {
-				Get();
-			} else {
-				Get();
-			}
-			String op = t.val; 
-			TypedNode right = Factor();
-			result = factory.createBinary(op, result, right); 
-		}
-		return result;
-	}
-
-	TypedNode  Factor() {
-		TypedNode  result;
-		result = null; 
-		switch (la.kind) {
-		case 27: {
-			result = TimeRef();
-			break;
-		}
-		case 1: {
-			result = VariableRef();
-			break;
-		}
-		case 2: {
-			result = StringLiteral();
-			break;
-		}
-		case 3: {
-			result = NumericLiteral();
-			break;
-		}
-		case 24: {
-			result = Ternary();
-			break;
-		}
-		case 8: {
-			Get();
-			result = Expression();
-			Expect(9);
-			break;
-		}
-		default: SynErr(30); break;
-		}
-		return result;
-	}
-
-	TypedNode  TimeRef() {
-		TypedNode  result;
-		Expect(27);
-		result = factory.createTime(); 
-		return result;
-	}
-
-	TypedNode  VariableRef() {
-		TypedNode  result;
-		Expect(1);
-		result = factory.createLocal(t.val); 
-		return result;
-	}
-
-	TypedNode  StringLiteral() {
-		TypedNode  result;
-		Expect(2);
-		result = factory.createStringLiteral(t.val.substring(1, t.val.length() - 1)); 
-		return result;
-	}
-
-	TypedNode  NumericLiteral() {
-		TypedNode  result;
-		Expect(3);
-		result = factory.createNumericLiteral(t.val); 
-		return result;
-	}
-
-	TypedNode  Ternary() {
-		TypedNode  result;
-		TypedNode condition, thenPart, elsePart; 
-		Expect(24);
-		condition = Expression();
-		Expect(25);
-		thenPart = Expression();
-		Expect(26);
-		elsePart = Expression();
-		result = factory.createTernary(condition, thenPart, elsePart); 
-		return result;
-	}
-
+	void SimpleLanguage() {
+		Function();
+		while (la.kind == 4) {
+			Function();
+		}
+	}
+
+	void Function() {
+		Expect(4);
+		factory.startFunction(); 
+		Expect(1);
+		String name = t.val; 
+		StatementNode body = Block();
+		factory.createFunction(body, name); 
+	}
+
+	StatementNode  Block() {
+		StatementNode  result;
+		List<StatementNode> statements = new ArrayList<>(); 
+		Expect(5);
+		while (StartOf(1)) {
+			StatementNode statement = Statement();
+			statements.add(statement); 
+		}
+		Expect(6);
+		result = factory.createBlock(statements); 
+		return result;
+	}
+
+	StatementNode  Statement() {
+		StatementNode  result;
+		result = null; 
+		if (la.kind == 7) {
+			result = WhileStatement();
+		} else if (la.kind == 1) {
+			result = AssignmentStatement();
+		} else if (la.kind == 12) {
+			result = OutputStatement();
+		} else if (la.kind == 13) {
+			result = ReturnStatement();
+		} else SynErr(29);
+		return result;
+	}
+
+	StatementNode  WhileStatement() {
+		StatementNode  result;
+		Expect(7);
+		Expect(8);
+		ConditionNode condition = Expression();
+		Expect(9);
+		StatementNode body = Block();
+		result = factory.createWhile(condition, body); 
+		return result;
+	}
+
+	StatementNode  AssignmentStatement() {
+		StatementNode  result;
+		Expect(1);
+		String name = t.val; 
+		Expect(10);
+		TypedNode rvalue = Expression();
+		Expect(11);
+		result = factory.createAssignment(name, rvalue); 
+		return result;
+	}
+
+	StatementNode  OutputStatement() {
+		StatementNode  result;
+		List<TypedNode> expressions = new ArrayList<>(); 
+		Expect(12);
+		while (StartOf(2)) {
+			TypedNode value = Expression();
+			expressions.add(value); 
+		}
+		Expect(11);
+		result = factory.createPrint(expressions); 
+		return result;
+	}
+
+	StatementNode  ReturnStatement() {
+		StatementNode  result;
+		Expect(13);
+		TypedNode value = Expression();
+		Expect(11);
+		result = factory.createReturn(value); 
+		return result;
+	}
+
+	TypedNode  Expression() {
+		TypedNode  result;
+		result = ValueExpression();
+		if (StartOf(3)) {
+			switch (la.kind) {
+			case 14: {
+				Get();
+				break;
+			}
+			case 15: {
+				Get();
+				break;
+			}
+			case 16: {
+				Get();
+				break;
+			}
+			case 17: {
+				Get();
+				break;
+			}
+			case 18: {
+				Get();
+				break;
+			}
+			case 19: {
+				Get();
+				break;
+			}
+			}
+			String op = t.val; 
+			TypedNode right = ValueExpression();
+			result = factory.createBinary(op, result, right); 
+		}
+		return result;
+	}
+
+	TypedNode  ValueExpression() {
+		TypedNode  result;
+		result = Term();
+		while (la.kind == 20 || la.kind == 21) {
+			if (la.kind == 20) {
+				Get();
+			} else {
+				Get();
+			}
+			String op = t.val; 
+			TypedNode right = Term();
+			result = factory.createBinary(op, result, right); 
+		}
+		return result;
+	}
+
+	TypedNode  Term() {
+		TypedNode  result;
+		result = Factor();
+		while (la.kind == 22 || la.kind == 23) {
+			if (la.kind == 22) {
+				Get();
+			} else {
+				Get();
+			}
+			String op = t.val; 
+			TypedNode right = Factor();
+			result = factory.createBinary(op, result, right); 
+		}
+		return result;
+	}
+
+	TypedNode  Factor() {
+		TypedNode  result;
+		result = null; 
+		switch (la.kind) {
+		case 27: {
+			result = TimeRef();
+			break;
+		}
+		case 1: {
+			result = VariableRef();
+			break;
+		}
+		case 2: {
+			result = StringLiteral();
+			break;
+		}
+		case 3: {
+			result = NumericLiteral();
+			break;
+		}
+		case 24: {
+			result = Ternary();
+			break;
+		}
+		case 8: {
+			Get();
+			result = Expression();
+			Expect(9);
+			break;
+		}
+		default: SynErr(30); break;
+		}
+		return result;
+	}
+
+	TypedNode  TimeRef() {
+		TypedNode  result;
+		Expect(27);
+		result = factory.createTime(); 
+		return result;
+	}
+
+	TypedNode  VariableRef() {
+		TypedNode  result;
+		Expect(1);
+		result = factory.createLocal(t.val); 
+		return result;
+	}
+
+	TypedNode  StringLiteral() {
+		TypedNode  result;
+		Expect(2);
+		result = factory.createStringLiteral(t.val.substring(1, t.val.length() - 1)); 
+		return result;
+	}
+
+	TypedNode  NumericLiteral() {
+		TypedNode  result;
+		Expect(3);
+		result = factory.createNumericLiteral(t.val); 
+		return result;
+	}
+
+	TypedNode  Ternary() {
+		TypedNode  result;
+		TypedNode condition, thenPart, elsePart; 
+		Expect(24);
+		condition = Expression();
+		Expect(25);
+		thenPart = Expression();
+		Expect(26);
+		elsePart = Expression();
+		result = factory.createTernary(condition, thenPart, elsePart); 
+		return result;
+	}
+
 
 
     public void Parse() {
         la = new Token();
         la.val = "";
         Get();
-		SimpleLanguage();
-		Expect(0);
+		SimpleLanguage();
+		Expect(0);
 
     }
 
     private static final boolean[][] set = {
-		{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
-		{x,T,x,x, x,x,x,T, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
-		{x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,T, x,x},
-		{x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x}
+		{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+		{x,T,x,x, x,x,x,T, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+		{x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,T, x,x},
+		{x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x}
 
     };
 
@@ -416,37 +416,37 @@
 
     public void SynErr(int line, int col, int n) {
         String s;
-        switch (n) {
-			case 0: s = "EOF expected"; break;
-			case 1: s = "identifier expected"; break;
-			case 2: s = "stringLiteral expected"; break;
-			case 3: s = "numericLiteral expected"; break;
-			case 4: s = "\"function\" expected"; break;
-			case 5: s = "\"{\" expected"; break;
-			case 6: s = "\"}\" expected"; break;
-			case 7: s = "\"while\" expected"; break;
-			case 8: s = "\"(\" expected"; break;
-			case 9: s = "\")\" expected"; break;
-			case 10: s = "\"=\" expected"; break;
-			case 11: s = "\";\" expected"; break;
-			case 12: s = "\"print\" expected"; break;
-			case 13: s = "\"return\" expected"; break;
-			case 14: s = "\"<\" expected"; break;
-			case 15: s = "\">\" expected"; break;
-			case 16: s = "\"<=\" expected"; break;
-			case 17: s = "\">=\" expected"; break;
-			case 18: s = "\"==\" expected"; break;
-			case 19: s = "\"!=\" expected"; break;
-			case 20: s = "\"+\" expected"; break;
-			case 21: s = "\"-\" expected"; break;
-			case 22: s = "\"*\" expected"; break;
-			case 23: s = "\"/\" expected"; break;
-			case 24: s = "\"#\" expected"; break;
-			case 25: s = "\"?\" expected"; break;
-			case 26: s = "\":\" expected"; break;
-			case 27: s = "\"time\" expected"; break;
-			case 28: s = "??? expected"; break;
-			case 29: s = "invalid Statement"; break;
+        switch (n) {
+			case 0: s = "EOF expected"; break;
+			case 1: s = "identifier expected"; break;
+			case 2: s = "stringLiteral expected"; break;
+			case 3: s = "numericLiteral expected"; break;
+			case 4: s = "\"function\" expected"; break;
+			case 5: s = "\"{\" expected"; break;
+			case 6: s = "\"}\" expected"; break;
+			case 7: s = "\"while\" expected"; break;
+			case 8: s = "\"(\" expected"; break;
+			case 9: s = "\")\" expected"; break;
+			case 10: s = "\"=\" expected"; break;
+			case 11: s = "\";\" expected"; break;
+			case 12: s = "\"print\" expected"; break;
+			case 13: s = "\"return\" expected"; break;
+			case 14: s = "\"<\" expected"; break;
+			case 15: s = "\">\" expected"; break;
+			case 16: s = "\"<=\" expected"; break;
+			case 17: s = "\">=\" expected"; break;
+			case 18: s = "\"==\" expected"; break;
+			case 19: s = "\"!=\" expected"; break;
+			case 20: s = "\"+\" expected"; break;
+			case 21: s = "\"-\" expected"; break;
+			case 22: s = "\"*\" expected"; break;
+			case 23: s = "\"/\" expected"; break;
+			case 24: s = "\"#\" expected"; break;
+			case 25: s = "\"?\" expected"; break;
+			case 26: s = "\":\" expected"; break;
+			case 27: s = "\"time\" expected"; break;
+			case 28: s = "??? expected"; break;
+			case 29: s = "invalid Statement"; break;
 			case 30: s = "invalid Factor"; break;
             default:
                 s = "error " + n;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java	Thu Sep 05 16:36:40 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java	Fri Sep 13 23:12:10 2013 +0200
@@ -21,7 +21,7 @@
  * questions.
  */
 
-// The content of this file is automatically generated. DO NOT EDIT.
+ // The content of this file is automatically generated. DO NOT EDIT.
 
 package com.oracle.truffle.sl.parser;
 
@@ -518,66 +518,66 @@
                 } // NextCh already done
 				case 1:
 					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
+					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
 					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
 				case 2:
-					if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;}
-					else if (ch == '"') {AddCh(); state = 3; break;}
+					if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;}
+					else if (ch == '"') {AddCh(); state = 3; break;}
 					else {state = 0; break;}
-				case 3:
+				case 3:
 					{t.kind = 2; break loop;}
 				case 4:
 					recEnd = pos; recKind = 3;
-					if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;}
+					if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;}
 					else {t.kind = 3; break loop;}
-				case 5:
+				case 5:
 					{t.kind = 3; break loop;}
-				case 6:
+				case 6:
 					{t.kind = 5; break loop;}
-				case 7:
+				case 7:
 					{t.kind = 6; break loop;}
-				case 8:
+				case 8:
 					{t.kind = 8; break loop;}
-				case 9:
+				case 9:
 					{t.kind = 9; break loop;}
-				case 10:
+				case 10:
 					{t.kind = 11; break loop;}
-				case 11:
+				case 11:
 					{t.kind = 16; break loop;}
-				case 12:
+				case 12:
 					{t.kind = 17; break loop;}
-				case 13:
+				case 13:
 					{t.kind = 18; break loop;}
 				case 14:
-					if (ch == '=') {AddCh(); state = 15; break;}
+					if (ch == '=') {AddCh(); state = 15; break;}
 					else {state = 0; break;}
-				case 15:
+				case 15:
 					{t.kind = 19; break loop;}
-				case 16:
+				case 16:
 					{t.kind = 20; break loop;}
-				case 17:
+				case 17:
 					{t.kind = 21; break loop;}
-				case 18:
+				case 18:
 					{t.kind = 22; break loop;}
-				case 19:
+				case 19:
 					{t.kind = 23; break loop;}
-				case 20:
+				case 20:
 					{t.kind = 24; break loop;}
-				case 21:
+				case 21:
 					{t.kind = 25; break loop;}
-				case 22:
+				case 22:
 					{t.kind = 26; break loop;}
 				case 23:
 					recEnd = pos; recKind = 10;
-					if (ch == '=') {AddCh(); state = 13; break;}
+					if (ch == '=') {AddCh(); state = 13; break;}
 					else {t.kind = 10; break loop;}
 				case 24:
 					recEnd = pos; recKind = 14;
-					if (ch == '=') {AddCh(); state = 11; break;}
+					if (ch == '=') {AddCh(); state = 11; break;}
 					else {t.kind = 14; break loop;}
 				case 25:
 					recEnd = pos; recKind = 15;
-					if (ch == '=') {AddCh(); state = 12; break;}
+					if (ch == '=') {AddCh(); state = 12; break;}
 					else {t.kind = 15; break loop;}
 
             }
--- a/mx/commands.py	Thu Sep 05 16:36:40 2013 +0200
+++ b/mx/commands.py	Fri Sep 13 23:12:10 2013 +0200
@@ -467,18 +467,21 @@
     env = os.environ.copy()
     env['PYTHONPATH'] = dirname(mx.__file__)
 
-    for root, _, filenames in os.walk(_graal_home):
-        for f in filenames:
-            if f.endswith('.py'):
-                pyfile = join(_graal_home, root, f)
-                mx.log('Running pylint on ' + pyfile + '...')
-                mx.run(['pylint', '--reports=n', '--rcfile=' + rcfile, pyfile], env=env)
+    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"""
+def jdkhome(vm=None):
+    """return the JDK directory selected for the 'vm' command"""
+    build = _vmbuild if _vmSourcesAvailable else 'product'
+    return _jdk(build, installGraalJar=False)
 
-    build = _vmbuild if _vmSourcesAvailable else 'product'
-    print _jdk(build, installGraalJar=False)
+def print_jdkhome(args, vm=None):
+    """print the JDK directory selected for the 'vm' command"""
+    print jdkhome(vm)
 
 def buildvars(args):
     """describe the variables that can be set by the -D option to the 'mx build' commmand"""
@@ -1358,7 +1361,7 @@
                     '--title', 'Graal OpenJDK Project Documentation',
                     '--dot-output-base', 'projects'] + args)
 
-def mx_init():
+def mx_init(suite):
     commands = {
         'build': [build, ''],
         'buildvars': [buildvars, ''],
@@ -1367,7 +1370,7 @@
         'hsdis': [hsdis, '[att]'],
         'hcfdis': [hcfdis, ''],
         'igv' : [igv, ''],
-        'jdkhome': [jdkhome, ''],
+        'jdkhome': [print_jdkhome, ''],
         'pylint': [pylint, ''],
         'dacapo': [dacapo, '[VM options] benchmarks...|"all" [DaCapo options]'],
         'scaladacapo': [scaladacapo, '[VM options] benchmarks...|"all" [Scala DaCapo options]'],
@@ -1406,7 +1409,7 @@
             'export': [export, '[-options] [zipfile]'],
         })
 
-    mx._commands.update(commands)
+    mx.update_commands(suite, commands)
 
 def mx_post_parse_cmd_line(opts):  #
     # TODO _minVersion check could probably be part of a Suite in mx?
--- a/mx/projects	Thu Sep 05 16:36:40 2013 +0200
+++ b/mx/projects	Fri Sep 13 23:12:10 2013 +0200
@@ -28,7 +28,7 @@
 library@OKRA@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.2.jar
 
 distribution@GRAAL@path=graal.jar
-distribution@GRAAL@dependencies=com.oracle.graal.hotspot.amd64,com.oracle.graal.truffle,com.oracle.graal.truffle.printer,com.oracle.graal.hotspot.sparc,com.oracle.graal.hotspot,com.oracle.graal.compiler.hsail
+distribution@GRAAL@dependencies=com.oracle.graal.hotspot.amd64,com.oracle.graal.hotspot.ptx,com.oracle.graal.truffle,com.oracle.graal.truffle.printer,com.oracle.graal.hotspot.sparc,com.oracle.graal.hotspot,com.oracle.graal.compiler.hsail
 
 # graal.api.runtime
 project@com.oracle.graal.api.runtime@subDir=graal
@@ -134,6 +134,15 @@
 project@com.oracle.graal.hotspot.sparc@javaCompliance=1.7
 project@com.oracle.graal.hotspot.sparc@workingSets=Graal,HotSpot,SPARC
 
+# graal.hotspot.ptx
+project@com.oracle.graal.hotspot.ptx@subDir=graal
+project@com.oracle.graal.hotspot.ptx@sourceDirs=src
+project@com.oracle.graal.hotspot.ptx@dependencies=com.oracle.graal.hotspot,com.oracle.graal.ptx
+project@com.oracle.graal.hotspot.ptx@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.hotspot.ptx@annotationProcessors=com.oracle.graal.service.processor
+project@com.oracle.graal.hotspot.ptx@javaCompliance=1.7
+project@com.oracle.graal.hotspot.ptx@workingSets=Graal,HotSpot,PTX
+
 # graal.hotspot.server
 project@com.oracle.graal.hotspot.server@subDir=graal
 project@com.oracle.graal.hotspot.server@sourceDirs=src
--- a/mx/sanitycheck.py	Thu Sep 05 16:36:40 2013 +0200
+++ b/mx/sanitycheck.py	Fri Sep 13 23:12:10 2013 +0200
@@ -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'],
 }
 
--- a/mxtool/mx.py	Thu Sep 05 16:36:40 2013 +0200
+++ b/mxtool/mx.py	Fri Sep 13 23:12:10 2013 +0200
@@ -37,7 +37,11 @@
 containing one or more projects. It's not coincidental that this closely
 matches the layout of one or more projects in a Mercurial repository.
 The configuration information for a suite lives in an 'mx' sub-directory
-at the top level of the suite.
+at the top level of the suite. A suite is given a name by a 'suite=name'
+property in the 'mx/projects' file (if omitted the name is suite directory).
+An 'mx' subdirectory can be named as plain 'mx' or 'mxbasename', where
+'basename' is the os.path.basename of the suite directory.
+The latter is useful to avoid clashes in IDE project names.
 
 When launched, mx treats the current working directory as a suite.
 This is the primary suite. All other suites are called included suites.
@@ -137,7 +141,7 @@
 Property values can use environment variables with Bash syntax (e.g. ${HOME}).
 """
 
-import sys, os, errno, time, subprocess, shlex, types, urllib2, contextlib, StringIO, zipfile, signal, xml.sax.saxutils, tempfile
+import sys, os, errno, time, subprocess, shlex, types, urllib2, contextlib, StringIO, zipfile, signal, xml.sax.saxutils, tempfile, fnmatch
 import textwrap
 import xml.parsers.expat
 import shutil, re, xml.dom.minidom
@@ -435,6 +439,23 @@
             if url.endswith('/') != self.path.endswith(os.sep):
                 abort('Path for dependency directory must have a URL ending with "/": path=' + self.path + ' url=' + url)
 
+    def __eq__(self, other):
+        if isinstance(other, Library):
+            if len(self.urls) == 0:
+                return self.path == other.path
+            else:
+                return self.urls == other.urls
+        else:
+            return NotImplemented
+
+
+    def __ne__(self, other):
+        result = self.__eq__(other)
+        if result is NotImplemented:
+            return result
+        return not result
+
+
     def get_path(self, resolve):
         path = self.path
         if not isabs(path):
@@ -468,15 +489,15 @@
         return deps
 
 class Suite:
-    def __init__(self, d, primary):
+    def __init__(self, d, mxDir, primary):
         self.dir = d
+        self.mxDir = mxDir
         self.projects = []
         self.libs = []
         self.dists = []
         self.includes = []
         self.commands = None
         self.primary = primary
-        mxDir = join(d, 'mx')
         self._load_env(mxDir)
         self._load_commands(mxDir)
         self._load_includes(mxDir)
@@ -590,7 +611,7 @@
             if hasattr(mod, 'mx_post_parse_cmd_line'):
                 self.mx_post_parse_cmd_line = mod.mx_post_parse_cmd_line
 
-            mod.mx_init()
+            mod.mx_init(self)
             self.commands = mod
 
     def _load_includes(self, mxDir):
@@ -600,7 +621,7 @@
                 for line in f:
                     include = expandvars_in_property(line.strip())
                     self.includes.append(include)
-                    _loadSuite(include, False)
+                    _loadSuite(os.path.abspath(include), False)
 
     def _load_env(self, mxDir):
         e = join(mxDir, 'env')
@@ -616,8 +637,7 @@
                         key, value = line.split('=', 1)
                         os.environ[key.strip()] = expandvars_in_property(value.strip())
     def _post_init(self, opts):
-        mxDir = join(self.dir, 'mx')
-        self._load_projects(mxDir)
+        self._load_projects(self.mxDir)
         for p in self.projects:
             existing = _projects.get(p.name)
             if existing is not None:
@@ -626,8 +646,9 @@
                 _projects[p.name] = p
         for l in self.libs:
             existing = _libs.get(l.name)
-            if existing is not None:
-                abort('cannot redefine library  ' + l.name)
+            # Check that suites that define same library are consistent
+            if existing is not None and existing != l:
+                abort('inconsistent library redefinition of ' + l.name + ' in ' + existing.suite.dir + ' and ' + l.suite.dir)
             _libs[l.name] = l
         for d in self.dists:
             existing = _dists.get(d.name)
@@ -729,12 +750,25 @@
         abort('Unknown operating system ' + sys.platform)
 
 def _loadSuite(d, primary=False):
-    mxDir = join(d, 'mx')
-    if not exists(mxDir) or not isdir(mxDir):
+    """
+    Load a suite from the 'mx' or 'mxbbb' subdirectory of d, where 'bbb' is basename of d
+    """
+    mxDefaultDir = join(d, 'mx')
+    name = os.path.basename(d)
+    mxTaggedDir = mxDefaultDir + name
+    mxDir = None
+    if exists(mxTaggedDir) and isdir(mxTaggedDir):
+        mxDir = mxTaggedDir
+    else:
+        if exists(mxDefaultDir) and isdir(mxDefaultDir):
+            mxDir = mxDefaultDir
+
+
+    if mxDir is None:
         return None
     if len([s for s in _suites.itervalues() if s.dir == d]) == 0:
-        s = Suite(d, primary)
-        _suites[s.name] = s
+        s = Suite(d, mxDir, primary)
+        _suites[name] = s
         return s
 
 def suites():
@@ -879,7 +913,7 @@
     """
     deps = []
     if projectNames is None:
-        projects = _projects.values()
+        projects = opt_limit_to_suite(_projects.values())
     else:
         projects = [project(name) for name in projectNames]
 
@@ -887,6 +921,17 @@
         p.all_deps(deps, includeLibs=includeLibs, includeAnnotationProcessors=includeAnnotationProcessors)
     return deps
 
+def opt_limit_to_suite(projects):
+    if _opts.specific_suite is None:
+        return projects
+    else:
+        result = []
+        for p in projects:
+            s = p.suite
+            if s.name == _opts.specific_suite:
+                result.append(p)
+        return result
+
 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.')
@@ -936,7 +981,8 @@
 
     def __init__(self):
         self.java_initialized = False
-        ArgumentParser.__init__(self, prog='mx')
+        # this doesn't resolve the right way, but can't figure out how to override _handle_conflict_resolve in _ActionsContainer
+        ArgumentParser.__init__(self, prog='mx', conflict_handler='resolve')
 
         self.add_argument('-v', action='store_true', dest='verbose', help='enable verbose output')
         self.add_argument('-V', action='store_true', dest='very_verbose', help='enable very verbose output')
@@ -950,6 +996,7 @@
         self.add_argument('--user-home', help='users home directory', metavar='<path>', default=os.path.expanduser('~'))
         self.add_argument('--java-home', help='bootstrap JDK installation directory (must be JDK 6 or later)', metavar='<path>')
         self.add_argument('--ignore-project', action='append', dest='ignored_projects', help='name of project to ignore', metavar='<name>', default=[])
+        self.add_argument('--suite', dest='specific_suite', help='limit command to given suite', default=None)
         if get_os() != 'windows':
             # Time outs are (currently) implemented with Unix specific functionality
             self.add_argument('--timeout', help='timeout (in seconds) for command', type=int, default=0, metavar='<secs>')
@@ -987,6 +1034,9 @@
         commandAndArgs = opts.__dict__.pop('commandAndArgs')
         return opts, commandAndArgs
 
+    def _handle_conflict_resolve(self, action, conflicting_actions):
+        self._handle_conflict_error(action, conflicting_actions)
+
 def _format_commands():
     msg = '\navailable commands:\n\n'
     for cmd in sorted(_commands.iterkeys()):
@@ -1997,7 +2047,7 @@
                 logv('[no Java sources in {0} - skipping]'.format(sourceDir))
                 continue
 
-            timestampFile = join(p.suite.dir, 'mx', 'checkstyle-timestamps', sourceDir[len(p.suite.dir) + 1:].replace(os.sep, '_') + '.timestamp')
+            timestampFile = join(p.suite.mxDir, 'checkstyle-timestamps', sourceDir[len(p.suite.dir) + 1:].replace(os.sep, '_') + '.timestamp')
             if not exists(dirname(timestampFile)):
                 os.makedirs(dirname(timestampFile))
             mustCheck = False
@@ -2083,10 +2133,10 @@
                                 elif name == 'error':
                                     errors.append('{}:{}: {}'.format(source[0], attrs['line'], attrs['message']))
 
-                            p = xml.parsers.expat.ParserCreate()
-                            p.StartElementHandler = start_element
+                            xp = xml.parsers.expat.ParserCreate()
+                            xp.StartElementHandler = start_element
                             with open(auditfileName) as fp:
-                                p.ParseFile(fp)
+                                xp.ParseFile(fp)
                             if len(errors) != 0:
                                 map(log, errors)
                                 totalErrors = totalErrors + len(errors)
@@ -2356,20 +2406,22 @@
                     out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + getattr(dep, 'eclipse.project')})
                 else:
                     path = dep.path
-                    if dep.mustExist:
-                        dep.get_path(resolve=True)
-                        if not isabs(path):
-                            # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
-                            # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
-                            # safest to simply use absolute paths.
-                            path = join(suite.dir, path)
-
-                        attributes = {'exported' : 'true', 'kind' : 'lib', 'path' : path}
-
-                        sourcePath = dep.get_source_path(resolve=True)
-                        if sourcePath is not None:
-                            attributes['sourcepath'] = sourcePath
-                        out.element('classpathentry', attributes)
+                    dep.get_path(resolve=True)
+                    if not exists(path) and not dep.mustExist:
+                        continue
+
+                    if not isabs(path):
+                        # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
+                        # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
+                        # safest to simply use absolute paths.
+                        path = join(p.suite.dir, path)
+
+                    attributes = {'exported' : 'true', 'kind' : 'lib', 'path' : path}
+
+                    sourcePath = dep.get_source_path(resolve=True)
+                    if sourcePath is not None:
+                        attributes['sourcepath'] = sourcePath
+                    out.element('classpathentry', attributes)
             else:
                 out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + dep.name})
 
@@ -2454,7 +2506,7 @@
         if not exists(settingsDir):
             os.mkdir(settingsDir)
 
-        eclipseSettingsDir = join(suite.dir, 'mx', 'eclipse-settings')
+        eclipseSettingsDir = join(p.suite.mxDir, 'eclipse-settings')
         if exists(eclipseSettingsDir):
             for name in os.listdir(eclipseSettingsDir):
                 if name == "org.eclipse.jdt.apt.core.prefs" and not len(p.annotation_processors()) > 0:
@@ -2482,7 +2534,7 @@
                                     # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
                                     # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
                                     # safest to simply use absolute paths.
-                                    path = join(suite.dir, path)
+                                    path = join(p.suite.dir, path)
                                 out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : path, 'enabled' : 'true', 'runInBatchMode' : 'false'})
                     else:
                         out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + dep.name + '/' + dep.name + '.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'})
@@ -2558,12 +2610,14 @@
 
     # identify the location where to look for workingsets.xml
     wsfilename = 'workingsets.xml'
+    wsloc = '.metadata/.plugins/org.eclipse.ui.workbench'
     wsroot = suite.dir
     if os.environ.has_key('WORKSPACE'):
         wsroot = os.environ['WORKSPACE']
-    wsdir = join(wsroot, '.metadata/.plugins/org.eclipse.ui.workbench')
+    wsdir = join(wsroot, wsloc)
     if not exists(wsdir):
         wsdir = wsroot
+        log('Could not find Eclipse metadata directory. Please place ' + wsfilename + ' in ' + wsloc + ' manually.')
     wspath = join(wsdir, wsfilename)
 
     # gather working set info from project data
@@ -2933,7 +2987,7 @@
                         shutil.rmtree(currentDir)
                         log('Deleted ' + currentDir)
 
-def javadoc(args, parser=None, docDir='javadoc', includeDeps=True):
+def javadoc(args, parser=None, docDir='javadoc', includeDeps=True, stdDoclet=True):
     """generate javadoc for some/all Java projects"""
 
     parser = ArgumentParser(prog='mx javadoc') if parser is None else parser
@@ -3035,10 +3089,14 @@
             nowarnAPI = []
             if not args.warnAPI:
                 nowarnAPI.append('-XDignore.symbol.file')
+
+            # windowTitle onloy applies to the standard doclet processor
+            windowTitle = []
+            if stdDoclet:
+                windowTitle = ['-windowtitle', p.name + ' javadoc']
             try:
                 log('Generating {2} for {0} in {1}'.format(p.name, out, docDir))
                 run([java().javadoc, memory,
-                     '-windowtitle', p.name + ' javadoc',
                      '-XDignore.symbol.file',
                      '-classpath', cp,
                      '-quiet',
@@ -3048,6 +3106,7 @@
                      links +
                      extraArgs +
                      nowarnAPI +
+                     windowTitle +
                      list(pkgs))
                 log('Generated {2} for {0} in {1}'.format(p.name, out, docDir))
             finally:
@@ -3436,6 +3495,14 @@
     assert _argParser is not None
     _argParser.add_argument(*args, **kwargs)
 
+def update_commands(suite, new_commands):
+    for key, value in new_commands.iteritems():
+        if _commands.has_key(key) and not suite.primary:
+            pass
+            # print("WARNING: attempt to redefine command '" + key + "' in suite " + suite.dir)
+        else:
+            _commands[key] = value
+
 # Table of commands in alphabetical order.
 # Keys are command names, value are lists: [<function>, <usage msg>, <format args to doc string of function>...]
 # If any of the format args are instances of Callable, then they are called with an 'env' are before being
@@ -3467,9 +3534,12 @@
 
 def _findPrimarySuite():
     def is_suite_dir(d):
-        mxDir = join(d, 'mx')
-        if exists(mxDir) and isdir(mxDir) and exists(join(mxDir, 'projects')):
-            return dirname(mxDir)
+        for f in os.listdir(d):
+            if fnmatch.fnmatch(f, 'mx*'):
+                mxDir = join(d, f)
+                if exists(mxDir) and isdir(mxDir) and exists(join(mxDir, 'projects')):
+                    return dirname(mxDir)
+
 
     # try current working directory first
     if is_suite_dir(os.getcwd()):
--- a/src/gpu/ptx/vm/gpu_ptx.cpp	Thu Sep 05 16:36:40 2013 +0200
+++ b/src/gpu/ptx/vm/gpu_ptx.cpp	Fri Sep 13 23:12:10 2013 +0200
@@ -29,7 +29,7 @@
 #include "utilities/ostream.hpp"
 #include "memory/allocation.hpp"
 #include "memory/allocation.inline.hpp"
-#include "kernelArguments.hpp"
+#include "ptxKernelArguments.hpp"
 
 void * gpu::Ptx::_device_context;
 int    gpu::Ptx::_cu_device = 0;
@@ -50,36 +50,6 @@
 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)
-  set_gpu_linkage(gpu::Ptx::probe_linkage());
-#else
-  set_gpu_linkage(false);
-#endif
-}
-
-void gpu::initialize_gpu() {
-  if (gpu::has_gpu_linkage()) {
-    set_initialized(gpu::Ptx::initialize_gpu());
-  }
-}
-
-void * gpu::generate_kernel(unsigned char *code, int code_len, const char *name) {
-  if (gpu::has_gpu_linkage()) {
-    return (gpu::Ptx::generate_kernel(code, code_len, name));
-  } else {
-    return NULL;
-  }
-}
-
-bool gpu::execute_kernel(address kernel, PTXKernelArguments & ptxka, JavaValue& ret) {
-  if (gpu::has_gpu_linkage()) {
-    return (gpu::Ptx::execute_kernel(kernel, ptxka, ret));
-  } else {
-    return false;
-  }
-}
-
 bool gpu::Ptx::initialize_gpu() {
 
   /* Initialize CUDA driver API */
--- a/src/gpu/ptx/vm/kernelArguments.cpp	Thu Sep 05 16:36:40 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * 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_*
--- a/src/gpu/ptx/vm/kernelArguments.hpp	Thu Sep 05 16:36:40 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
- * 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gpu/ptx/vm/ptxKernelArguments.cpp	Fri Sep 13 23:12:10 2013 +0200
@@ -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 "ptxKernelArguments.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/ptxKernelArguments.hpp	Fri Sep 13 23:12:10 2013 +0200
@@ -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/bsd_ptx/vm/gpu_bsd.cpp	Thu Sep 05 16:36:40 2013 +0200
+++ b/src/os_gpu/bsd_ptx/vm/gpu_bsd.cpp	Fri Sep 13 23:12:10 2013 +0200
@@ -33,6 +33,7 @@
    * a better detection solution for NVIDA PTX and AMD HSAIL.
    */
   set_available(true);
+  set_target_il_type(gpu::PTX);
   if (TraceGPUInteraction) {
     tty->print_cr("gpu_bsd::probe_gpu(APPLE): %d", gpu::is_available());
   }
--- a/src/os_gpu/linux_ptx/vm/gpu_linux.cpp	Thu Sep 05 16:36:40 2013 +0200
+++ b/src/os_gpu/linux_ptx/vm/gpu_linux.cpp	Fri Sep 13 23:12:10 2013 +0200
@@ -39,32 +39,40 @@
  */
 
 static unsigned int nvidia_vendor_id = 0x10de;
+static unsigned int amd_vendor_id = 0x1002;
 
 bool gpu::Linux::probe_gpu() {
   /* 
-   * Open /proc/bus/pci/devices to look for the first CUDA enabled
-   * device. For now, finding the first CUDA device. Will need to
-   * revisit this to support execution on multiple CUDA devices if
-   * they exist.
+   * Open /proc/bus/pci/devices to look for the first GPU device. For
+   * now, we will just find the first GPU device. Will need to revisit
+   * this to support execution on multiple GPU devices, if they exist.
    */
   FILE *pci_devices = fopen("/proc/bus/pci/devices", "r");
   char contents[4096];
   unsigned int bus_num_devfn_ign;
   unsigned int vendor;
   unsigned int device;
-  bool cuda_device_exists = false;
+  bool gpu_device_exists = false;
   if (pci_devices == NULL) {
     tty->print_cr("*** Failed to open /proc/bus/pci/devices");
-    return cuda_device_exists;
+    return gpu_device_exists;
   }
 
   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. */
+    /* Break after finding the first GPU device. */
     if (vendor == nvidia_vendor_id) {
-      cuda_device_exists = true;
+      gpu_device_exists = true;
+      set_target_il_type(gpu::PTX);
       if (TraceGPUInteraction) {
-        tty->print_cr("Found supported nVidia CUDA device vendor : 0x%04x device 0x%04x", vendor, device);
+        tty->print_cr("Found supported nVidia GPU device vendor : 0x%04x device 0x%04x", vendor, device);
+      }
+      break;
+    } else if (vendor == amd_vendor_id) {
+      gpu_device_exists = true;
+      set_target_il_type(gpu::HSAIL);
+      if (TraceGPUInteraction) {
+        tty->print_cr("Found supported AMD GPU device vendor : 0x%04x device 0x%04x", vendor, device);
       }
       break;
     }
@@ -73,5 +81,5 @@
   // Close file pointer.
   fclose(pci_devices);
 
-  return cuda_device_exists;
+  return gpu_device_exists;
 }
--- a/src/share/vm/classfile/vmSymbols.hpp	Thu Sep 05 16:36:40 2013 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Fri Sep 13 23:12:10 2013 +0200
@@ -311,6 +311,7 @@
   template(com_oracle_graal_hotspot_meta_HotSpotResolvedObjectType,  "com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType")       \
   template(com_oracle_graal_hotspot_meta_HotSpotMonitorValue,        "com/oracle/graal/hotspot/meta/HotSpotMonitorValue")             \
   template(com_oracle_graal_hotspot_debug_LocalImpl,                 "com/oracle/graal/hotspot/debug/LocalImpl")                      \
+  template(com_oracle_graal_hotspot_ptx_PTXHotSpotGraalRuntime,      "com/oracle/graal/hotspot/ptx/PTXHotSpotGraalRuntime")\
   AMD64_ONLY(template(com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime,"com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime"))\
   SPARC_ONLY(template(com_oracle_graal_hotspot_sparc_SPARCHotSpotGraalRuntime,"com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime"))\
   /* graal.api.meta */                                                                                                                \
@@ -356,6 +357,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	Thu Sep 05 16:36:40 2013 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Fri Sep 13 23:12:10 2013 +0200
@@ -95,6 +95,8 @@
         vm_abort(false);
       }
     }
+    VMToCompiler::finalizeOptions(CITime);
+
     if (UseCompiler) {
       VMToCompiler::startCompiler(BootstrapGraal);
       _initialized = true;
--- a/src/share/vm/graal/graalCompilerToGPU.cpp	Thu Sep 05 16:36:40 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToGPU.cpp	Fri Sep 13 23:12:10 2013 +0200
@@ -28,7 +28,7 @@
 #include "graal/graalJavaAccess.hpp"
 #include "runtime/gpu.hpp"
 #include "runtime/javaCalls.hpp"
-# include "ptx/vm/kernelArguments.hpp"
+# include "ptx/vm/ptxKernelArguments.hpp"
 
 // Entry to native method implementation that transitions current thread to '_thread_in_vm'.
 #define C2V_VMENTRY(result_type, name, signature) \
--- a/src/share/vm/graal/graalVMToCompiler.cpp	Thu Sep 05 16:36:40 2013 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.cpp	Fri Sep 13 23:12:10 2013 +0200
@@ -24,6 +24,7 @@
 #include "precompiled.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "graal/graalVMToCompiler.hpp"
+#include "runtime/gpu.hpp"
 
 // this is a *global* handle
 jobject VMToCompiler::_graalRuntimePermObject = NULL;
@@ -60,7 +61,18 @@
 Handle VMToCompiler::graalRuntime() {
   if (JNIHandles::resolve(_graalRuntimePermObject) == NULL) {
 #ifdef AMD64
-    Symbol* name = vmSymbols::com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime();
+    Symbol* name = NULL;
+    if (UseGPU) {
+      // Set name to PTXHotSpotRuntime if nVidia GPU was detected.
+      if ((gpu::get_target_il_type() == gpu::PTX) &&
+          gpu::is_available() && gpu::has_gpu_linkage()) {
+        name = vmSymbols::com_oracle_graal_hotspot_ptx_PTXHotSpotGraalRuntime();
+      }
+      // Set name to corresponding runtime classname for other
+      // supported GPU runtimes, here.
+    } else {
+      name = vmSymbols::com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime();
+    }
 #endif
 #ifdef SPARC
     Symbol* name = vmSymbols::com_oracle_graal_hotspot_sparc_SPARCHotSpotGraalRuntime();
@@ -90,23 +102,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	Thu Sep 05 16:36:40 2013 +0200
+++ b/src/share/vm/graal/graalVMToCompiler.hpp	Fri Sep 13 23:12:10 2013 +0200
@@ -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/globals.hpp	Thu Sep 05 16:36:40 2013 +0200
+++ b/src/share/vm/runtime/globals.hpp	Fri Sep 13 23:12:10 2013 +0200
@@ -3717,8 +3717,11 @@
   product(bool , AllowNonVirtualCalls, false,                               \
           "Obey the ACC_SUPER flag and allow invokenonvirtual calls")       \
                                                                             \
-  product(bool, TraceGPUInteraction, false,                                    \
-          "Trace external GPU warp loading")                                \
+  product(bool, TraceGPUInteraction, false,                                 \
+          "Trace external GPU Interaction")                                 \
+                                                                            \
+  product(bool, UseGPU, false,                                              \
+          "Run code on GPU")                                                \
                                                                             \
   diagnostic(ccstr, SharedArchiveFile, NULL,                                \
           "Override the default location of the CDS archive file")          \
--- a/src/share/vm/runtime/gpu.cpp	Thu Sep 05 16:36:40 2013 +0200
+++ b/src/share/vm/runtime/gpu.cpp	Fri Sep 13 23:12:10 2013 +0200
@@ -25,14 +25,48 @@
 #include "precompiled.hpp"
 #include "runtime/gpu.hpp"
 
-bool gpu::_available = false;   // does the hardware exist?
-bool gpu::_gpu_linkage = false; // is the driver library to access the GPU installed
-bool gpu::_initialized = false; // is the GPU device initialized
+bool gpu::_available = false;    // does the hardware exist?
+bool gpu::_gpu_linkage = false;  // is the driver library to access the GPU installed
+bool gpu::_initialized = false;  // is the GPU device initialized
+gpu::TargetGPUIL gpu::_targetIL = gpu::NONE; // No GPU detected yet.
 
 void gpu::init() {
 #if defined(TARGET_OS_FAMILY_bsd) || defined(TARGET_OS_FAMILY_linux)
   gpu::probe_gpu();
+  if (gpu::get_target_il_type() == gpu::PTX) {
+    set_gpu_linkage(gpu::Ptx::probe_linkage());
+  } else {
+    set_gpu_linkage(false);
+  }
 #endif
-  // need multi-gpu TARGET ifdef
-  gpu::probe_linkage();
+}
+
+void gpu::initialize_gpu() {
+  if (gpu::has_gpu_linkage()) {
+    if (gpu::get_target_il_type() == gpu::PTX) {
+      set_initialized(gpu::Ptx::initialize_gpu());
+    }
+    // Add initialization of other GPUs here
+  }
 }
+
+void * gpu::generate_kernel(unsigned char *code, int code_len, const char *name) {
+  if (gpu::has_gpu_linkage()) {
+    if (gpu::get_target_il_type() == gpu::PTX) {
+      return (gpu::Ptx::generate_kernel(code, code_len, name));
+    }
+    // Add kernel generation functionality of other GPUs here
+  }
+  return NULL;
+}
+
+bool gpu::execute_kernel(address kernel, PTXKernelArguments & ptxka, JavaValue& ret) {
+  if (gpu::has_gpu_linkage()) {
+    if (gpu::get_target_il_type() == gpu::PTX) {
+      return (gpu::Ptx::execute_kernel(kernel, ptxka, ret));
+    }
+    // Add kernel execution functionality of other GPUs here
+  }
+  return false;
+}
+
--- a/src/share/vm/runtime/gpu.hpp	Thu Sep 05 16:36:40 2013 +0200
+++ b/src/share/vm/runtime/gpu.hpp	Fri Sep 13 23:12:10 2013 +0200
@@ -36,12 +36,12 @@
 
 class gpu: AllStatic {
 public:
+
+  enum TargetGPUIL { NONE = 0, PTX = 1, HSAIL = 2};
   static void init(void);
 
   static void probe_gpu();
 
-  static void probe_linkage();
-  
   static void initialize_gpu();
   
   static void * generate_kernel(unsigned char *code, int code_len, const char *name);
@@ -66,10 +66,19 @@
 
   static bool has_gpu_linkage() { return _gpu_linkage; }
 
+  static void set_target_il_type(TargetGPUIL value) {
+    _targetIL = value;
+  }
+
+  static enum gpu::TargetGPUIL get_target_il_type() {
+    return _targetIL;
+  }
+
 protected:
   static bool _available;
   static bool _gpu_linkage;
   static bool _initialized;
+  static TargetGPUIL _targetIL;
 
   // Platform dependent stuff
 #ifdef TARGET_OS_FAMILY_linux